Eu quero usar find
para encontrar arquivos em um conjunto de pastas restritas por curingas, mas onde existem espaços no nome do caminho.
Na linha de comando, isso é fácil. Os exemplos a seguir todos funcionam.
find te*/my\ files/more -print
find te*/'my files'/more -print
find te*/my' 'files/more -print
Eles encontrarão arquivos em, por exemplo, terminal/my files/more
e tepid/my files/more
.
No entanto, eu preciso que isso faça parte de um script; o que eu preciso é algo como isto:
SEARCH='te*/my\ files/more'
find ${SEARCH} -print
Infelizmente, não importa o que eu faça, não consigo misturar curingas e espaços em um find
comando em um script. O exemplo acima retorna os seguintes erros (observe a duplicação inesperada da barra invertida):
find: ‘te*/my\\’: No such file or directory
find: ‘files/more’: No such file or directory
A tentativa de usar aspas também falha.
SEARCH="te*/'my files'/more"
find ${SEARCH} -print
Isso retorna os seguintes erros, tendo ignorado o significado das aspas:
find: ‘te*/'my’: No such file or directory
find: ‘files'/more’: No such file or directory
Aqui está mais um exemplo.
SEARCH='te*/my files/more'
find ${SEARCH} -print
Como esperado:
find: ‘te*/my’: No such file or directory
find: ‘files/more’: No such file or directory
Toda variação que eu tentei retorna um erro.
Eu tenho uma solução alternativa, que é potencialmente perigosa porque retorna muitas pastas. Converto todos os espaços em um ponto de interrogação (curinga de um caractere) assim:
SEARCH='te*/my files/more'
SEARCH=${SEARCH// /?} # Convert every space to a question mark.
find ${SEARCH} -print
Isso é equivalente a:
find te*/my?files/more -print
Isso retorna não apenas as pastas corretas, mas também o terse/myxfiles/more
que não deveria.
Como posso conseguir o que estou tentando fazer? O Google não me ajudou :(
SEARCH: command not found
com o comandofind -print
sendo executado.find "${SEARCH}" -print
?te*/'my files'/more
.Respostas:
O mesmo comando exato deve funcionar bem em um script:
Se você precisar tê-lo como variável, fica um pouco mais complexo:
ATENÇÃO:
Usar
eval
dessa maneira não é seguro e pode resultar na execução de código arbitrário e possivelmente prejudicial se os nomes dos arquivos puderem conter determinados caracteres. Consulte o FAQ do bash 48 para obter detalhes.É melhor seguir o caminho como argumento:
Outra abordagem é evitar
find
completamente e usar os recursos e globs estendidos do bash:A
globstar
opção bash permite usar**
para corresponder recursivamente:Para fazê-lo funcionar 100% como encontrar e incluir arquivos de ponto (arquivos ocultos), use
Você pode nivelá-
echo
los diretamente sem o loop:fonte
E matrizes?
(*)
expande para uma matriz do que corresponder ao curinga. E se"${SEARCH[@]}"
expande para todos os elementos da matriz ([@]
), com cada um deles citado individualmente.Tarde, eu percebo que acho que deveria ser capaz disso. Algo como:
fonte
INPUTPATH='te*/my files/more
eSEARCH=(${INPUTPATH})
. Não importa como eu varie da maneira que faço isso, ainda assim eu acabo com um resultado não funcional. Isso parece impossível!find
o-path
filtro? Ele usa curingas e definitivamente não precisa de expansão.-path
. Nos últimos 10 minutos, porém, eu descobri a resposta: useeval
! Parece ser mais simples que-path
.Eu finalmente descobri a resposta.
Adicione uma barra invertida a todos os espaços:
Neste ponto,
SEARCH
contémte*/my\ files/more
.Então use
eval
.É simples assim! Usar
eval
ignora a interpretação que${SEARCH}
é de uma variável.fonte