La mia migliore scommessa attuale è:
for i in $(find . -name *.jpg); do echo $i; done
Problema: non gestisce gli spazi nei nomi dei file.
Nota: mi piacerebbe anche un modo grafico per farlo, come il comando "albero".
La mia migliore scommessa attuale è:
for i in $(find . -name *.jpg); do echo $i; done
Problema: non gestisce gli spazi nei nomi dei file.
Nota: mi piacerebbe anche un modo grafico per farlo, come il comando "albero".
Risposte:
Il modo canonico è fare
find . -name '*.jpg' -exec echo {} \;
(sostituire \;
con +
per passare più di un file alla echo
volta)
o (specifico per GNU, anche se alcuni BSD ora lo hanno anche):
find . -name '*.jpg' -print0 | xargs -r0 echo
zsh:
for i (**/*.jpg(D)) echo $i
echo
che espande sequenze di escape come \b
(almeno le conformi Unix echo
).
find
pagina man viene mostrata find . -type f -exec file '{}' \;
nella EXAMPLES
sezione. Forse alcuni gusci tratteranno specialmente le parentesi graffe.
'{}'
, \{\}
, {}
, "{}"
, '{'}
sono espansi dalla shell (qualunque sia Bourne-come shell) per un argomento di trovare cioè i due caratteri "{" e "}". Sostituisci "trova" con "trova eco", o printf '<%s>\n' find
se vuoi ricontrollare.
Sono già state fornite risposte migliori.
Ma nota che gli spazi non sono l'unico problema nel codice che hai dato. anche i caratteri tab, newline e jolly sono un problema.
Con
IFS='
'
set -f
for i in $(find . -name '*.jpg'); do echo "$i"; done
Quindi solo i caratteri di nuova riga sono un problema.
Quello che hai menzionato è uno dei problemi di base che le persone affrontano quando provano a leggere i nomi dei file. A volte, le persone con una conoscenza limitata e con un'idea sbagliata della struttura di file e cartelle tendono a dimenticare che " In UNIX Tutto è un file ". Quindi non comprendono che devono gestire anche gli spazi, poiché il nome del file può essere composto da 2 o più parole con spazi.
Soluzione: uno dei modi più conosciuti per farlo è fare una lettura chiara .
Qui leggeremo tutti i file presenti e li terremo in una variabile, la prossima volta quando eseguiremo l'elaborazione desiderata dovremo semplicemente mantenere quella variabile tra virgolette che conserverà i nomi dei file con spazi. Questo è uno dei modi di base per farlo, tuttavia, le altre risposte fornite dalle altre persone qui funzionano altrettanto bene.
SCRIPT:
find /path/to/files/ -iname "*jpg" | \
while read I; do
cp -v --parent "$I" /backup/dir/
done
Qui sto leggendo i file dando loro il percorso e qualunque cosa io stia leggendo li mantengo all'interno di una variabile I, che citerò in un secondo momento durante l'elaborazione per preservare gli spazi in modo da elaborarli correttamente.
Spero che questo ti aiuti in qualche modo.
Semplicemente con find
e bash
:
find . -name '*.jpg' -exec bash -c '
echo "treating file $1 in bash, from path : ${1%/*}"
' -- {} \;
In questo modo, usiamo $1
in bash, come in uno script di base, che aprono belle prospettive per eseguire qualsiasi attività avanzata (o meno).
Un modo più efficiente (per evitare di dover iniziare un nuovo bash per ogni file):
find . -name '*.jpg' -exec bash -c 'for i do
echo "treating file $i in bash, from path : ${i%/*}"
done' -- {} +
Nella versione recente di bash, è possibile utilizzare globstar
opzione:
shopt -s globstar
for file in **/*.jpg ; do
echo "$file"
done
Per azioni semplici, puoi anche saltare completamente il loop:
echo **/*.jpg
set -G
), non dovrebbe essere usato in bash poiché la versione bash è sostanzialmente rotta (proprio come GNU grep -r
) mentre scende in collegamenti simbolici alle directory (equivalenti a find -L
o zsh ***/*.jpg
). Nota anche che, contrariamente a trovare, ommiterà di dotfile e non scenderà in dotdir (per impostazione predefinita).
$i
? Lo faccio e funziona benissimo. C'è qualcosa di sbagliato in questo approccio?