Mój obecny najlepszy zakład to:
for i in $(find . -name *.jpg); do echo $i; done
Problem: nie obsługuje spacji w nazwach plików.
Uwaga: Chciałbym też graficznie to zrobić, na przykład polecenie „drzewo”.
Mój obecny najlepszy zakład to:
for i in $(find . -name *.jpg); do echo $i; done
Problem: nie obsługuje spacji w nazwach plików.
Uwaga: Chciałbym też graficznie to zrobić, na przykład polecenie „drzewo”.
Odpowiedzi:
Kanoniczny sposób to zrobić
find . -name '*.jpg' -exec echo {} \;
(wymienić \;
z +
przejść więcej niż jeden plik echo
na raz)
lub (specyficzne dla GNU, chociaż niektóre BSD również je teraz mają):
find . -name '*.jpg' -print0 | xargs -r0 echo
zsh:
for i (**/*.jpg(D)) echo $i
echo
które rozszerza sekwencje specjalne\b
(przynajmniej zgodne z Unixem echo
).
find
man pokazuje find . -type f -exec file '{}' \;
w EXAMPLES
sekcji. Może niektóre pociski specjalnie potraktują aparat ortodontyczny.
'{}'
, \{\}
, {}
, "{}"
, '{'}
są rozszerzane przez powłokę (cokolwiek podobnego Bourne shell) do jednego argumentu do stwierdzenia, że jest dwa znaki „{” i „}”. Zamień „znajdź” na „znajdź echo” lub printf '<%s>\n' find
jeśli chcesz dwukrotnie sprawdzić.
Podano już lepsze odpowiedzi.
Pamiętaj jednak, że spacje nie są jedynym problemem w podanym kodzie. Problem stanowią także tabulatory, znaki nowej linii i znaki wieloznaczne.
Z
IFS='
'
set -f
for i in $(find . -name '*.jpg'); do echo "$i"; done
Wtedy problem stanowią tylko znaki nowej linii.
To, o czym wspomniałeś, jest jednym z podstawowych problemów, z którymi borykają się ludzie, gdy próbują odczytać nazwy plików. Czasami ludzie z ograniczoną wiedzą i nieporozumieniem co do struktury plików i folderów zwykle zapominają, że „ W UNIX Wszystko jest plikiem ”. Dlatego nie rozumieją, że muszą również obsługiwać spacje, ponieważ nazwa pliku może składać się z 2 lub więcej słów ze spacjami.
Rozwiązanie: Więc jednym z bardziej znanych sposobów na zrobienie tego jest czyste czytanie .
Przeczytamy wszystkie obecne pliki i zachowamy je w zmiennej, następnym razem, gdy wykonamy pożądane przetwarzanie, będziemy musieli po prostu zachować tę zmienną w cudzysłowach, co pozwoli zachować nazwy plików ze spacjami. Jest to jeden z podstawowych sposobów, aby to zrobić, jednak inne odpowiedzi udzielone przez innych ludzi tutaj również działają.
PISMO:
find /path/to/files/ -iname "*jpg" | \
while read I; do
cp -v --parent "$I" /backup/dir/
done
Tutaj czytam pliki, podając ścieżkę do nich, i cokolwiek czytam, przechowuję je w zmiennej I, którą zacytuję w późniejszym czasie, przetwarzając ją, aby zachować spacje, aby poprawnie ją przetworzyć.
Mam nadzieję, że to ci w jakiś sposób pomoże.
Po prostu za pomocą find
i bash
:
find . -name '*.jpg' -exec bash -c '
echo "treating file $1 in bash, from path : ${1%/*}"
' -- {} \;
W ten sposób używamy $1
w bash, podobnie jak w podstawowym skrypcie, który otwiera ładne perspektywy do wykonywania wszelkich zaawansowanych (lub nie) zadań.
Wydajniejszy sposób (aby uniknąć konieczności rozpoczynania nowego basha dla każdego pliku):
find . -name '*.jpg' -exec bash -c 'for i do
echo "treating file $i in bash, from path : ${i%/*}"
done' -- {} +
W najnowszej wersji bash możesz użyć globstar
opcji:
shopt -s globstar
for file in **/*.jpg ; do
echo "$file"
done
W przypadku prostych akcji możesz nawet całkowicie pominąć pętlę:
echo **/*.jpg
set -G
), nie należy go używać w bash, ponieważ wersja bash jest zasadniczo zepsuta (podobnie jak GNU grep -r
), ponieważ schodzi do dowiązań symbolicznych do katalogów (odpowiednik find -L
lub zsh ***/*.jpg
). Zauważ też, że w przeciwieństwie do znajdowania, będzie on opuszczał pliki kropkowe i nie opadał do kropek (domyślnie).
$i
? Robię to i działa dobrze. Czy jest coś nie tak z tym podejściem?