Minha melhor aposta atual é:
for i in $(find . -name *.jpg); do echo $i; done
Problema: não manipula espaços nos nomes de arquivos.
Nota: Eu também adoraria uma maneira gráfica de fazer isso, como o comando "tree".
Minha melhor aposta atual é:
for i in $(find . -name *.jpg); do echo $i; done
Problema: não manipula espaços nos nomes de arquivos.
Nota: Eu também adoraria uma maneira gráfica de fazer isso, como o comando "tree".
Respostas:
A maneira canônica é fazer
find . -name '*.jpg' -exec echo {} \;
(substitua \;
por +
para passar mais de um arquivo echo
por vez)
ou (específico do GNU, embora alguns BSDs agora também o tenham):
find . -name '*.jpg' -print0 | xargs -r0 echo
zsh:
for i (**/*.jpg(D)) echo $i
echo
que expande seqüências de escape como \b
(pelo menos os conformes do Unix echo
).
find
manual é exibida find . -type f -exec file '{}' \;
na EXAMPLES
seção. Talvez algumas conchas tratem o aparelho especialmente.
'{}'
, \{\}
, {}
, "{}"
, '{'}
são expandidos pela shell (o que quer Bourne-como shell) para um argumento para descobrir que é os dois personagens "{" e "}". Substitua "find" por "echo find" ou printf '<%s>\n' find
se desejar verificar novamente .
Melhores respostas já foram dadas.
Mas observe que os espaços não são o único problema no código que você forneceu. guia, caracteres de nova linha e curinga também são um problema.
Com
IFS='
'
set -f
for i in $(find . -name '*.jpg'); do echo "$i"; done
Somente caracteres de nova linha são um problema.
O que você mencionou é um dos problemas básicos que as pessoas enfrentam quando tentam ler os nomes dos arquivos. Às vezes, pessoas com conhecimento limitado e com uma concepção equivocada da estrutura de arquivos e pastas tendem a esquecer que " No UNIX, tudo é um arquivo ". Portanto, eles não entendem que precisam lidar com espaços também, pois o nome do arquivo pode consistir em 2 ou mais palavras com espaços.
Solução: Portanto, uma das maneiras mais conhecidas de fazer isso é fazer uma leitura limpa .
Aqui, leremos todos os arquivos presentes e os manteremos em uma variável. Da próxima vez que realizarmos o processamento desejado, teremos que manter essa variável entre aspas, o que preservará os nomes dos arquivos com espaços. Essa é uma das maneiras básicas de fazê-lo, no entanto, as outras respostas fornecidas pelas outras pessoas aqui também funcionam.
ROTEIRO :
find /path/to/files/ -iname "*jpg" | \
while read I; do
cp -v --parent "$I" /backup/dir/
done
Aqui eu estou lendo os arquivos, fornecendo o caminho para eles e o que quer que esteja lendo, eu os mantenho dentro de uma variável I, que citarei posteriormente, enquanto o processo para preservar os espaços e processá-los corretamente.
Espero que isso ajude você de alguma forma.
Simplesmente com find
e bash
:
find . -name '*.jpg' -exec bash -c '
echo "treating file $1 in bash, from path : ${1%/*}"
' -- {} \;
Dessa forma, usamos $1
no bash, como em um script básico, que abre boas perspectivas para executar tarefas avançadas (ou não).
Uma maneira mais eficiente (para evitar a necessidade de iniciar um novo bash para cada arquivo):
find . -name '*.jpg' -exec bash -c 'for i do
echo "treating file $i in bash, from path : ${i%/*}"
done' -- {} +
Na versão recente do bash, você pode usar a globstar
opção:
shopt -s globstar
for file in **/*.jpg ; do
echo "$file"
done
Para ações simples, você pode até pular o loop completamente:
echo **/*.jpg
set -G
), ele não deve ser usado no bash, pois a versão do bash é fundamentalmente quebrada (assim como o GNU grep -r
), pois desce para links simbólicos para diretórios (equivalentes aos do find -L
zsh ***/*.jpg
) Observe também que, diferentemente da localização, ele omitirá arquivos de ponto e não descerá em pontos de ponto (por padrão).
$i
? Eu faço isso e funciona bem. Há algo de errado com essa abordagem?