Jeśli używasz xargs -0 , powinieneś dopasować go do find -0
itsbruce
1
@ MichaelKjörling, brak cytowania {} nie ma znaczenia. {} jest rozszerzone przez find, a nie powłokę. Ulepszeniem byłoby nieużywanie, echoktóre rozszerza sekwencje specjalne\b (przynajmniej zgodne z Unixem echo).
Stéphane Chazelas
1
@sch Jesteś pewien? Strona findman pokazuje find . -type f -exec file '{}' \;w EXAMPLESsekcji. Może niektóre pociski specjalnie potraktują aparat ortodontyczny.
QuasarDonkey
1
Cytaty nie szkodzą, ale nie mają znaczenia. Wszystko '{}', \{\}, {}, "{}", '{'}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' findjeśli chcesz dwukrotnie sprawdzić.
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ą.
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ć.
„wszystko jest plikiem” odnosi się do czegoś innego. Twoje rozwiązanie jest specyficzne dla GUN i nie radzi sobie z odwrotnym ukośnikiem lub znakami nowej linii w nazwach plików. Pętle „podczas odczytu” w powłokach (IMO) są często oznaką złej praktyki pisania skryptów w powłokach.
Stéphane Chazelas,
@sch: huh, i myślałem, że jest w porządku. Dziękujemy za zwrócenie na to uwagi. Prawdopodobnie muszę na to więcej spojrzeć.
The Dark Knight
przepraszam, miałem na myśli „GNU”, a nie „GUN” powyżej (po raz pierwszy zdaję sobie sprawę, że to anagramy BTW ...)
Stéphane Chazelas,
1
Po prostu za pomocą findi bash:
find .-name '*.jpg'-exec bash -c '
echo "treating file $1 in bash, from path : ${1%/*}"
'--{} \;
W ten sposób używamy $1w 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'--{}+
Chociaż działa to w Zsh (skąd pochodzi ta funkcja) oraz w ksh93 (z 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 -Llub 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?Odpowiedzi:
Kanoniczny sposób to zrobić
(wymienić
\;
z+
przejść więcej niż jeden plikecho
na raz)lub (specyficzne dla GNU, chociaż niektóre BSD również je teraz mają):
zsh:
źródło
echo
które rozszerza sekwencje specjalne\b
(przynajmniej zgodne z Unixemecho
).find
man pokazujefind . -type f -exec file '{}' \;
wEXAMPLES
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” lubprintf '<%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
Wtedy problem stanowią tylko znaki nowej linii.
źródło
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:
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.
źródło
Po prostu za pomocą
find
ibash
: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):
źródło
W najnowszej wersji bash możesz użyć
globstar
opcji:W przypadku prostych akcji możesz nawet całkowicie pominąć pętlę:
źródło
set -G
), nie należy go używać w bash, ponieważ wersja bash jest zasadniczo zepsuta (podobnie jak GNUgrep -r
), ponieważ schodzi do dowiązań symbolicznych do katalogów (odpowiednikfind -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).