Po pierwsze, -i
przełącznik jest przestarzały:
-i[replace-str]
This option is a synonym for -Ireplace-str if replace-str is specified.
If the replace-str argument is missing, the effect is the same as -I{}.
This option is deprecated; use -I instead.
Kiedy zmieniłem twoje polecenie na to, zadziałało:
$ find /foo/bar -name '*.mp4' -print0 | xargs -I{} -0 mv -t /some/path {}
Przykład
$ find . -print0 | xargs -I{} -0 echo {}
.
./.sshmenu
./The GIT version control system.html
./.vim_SO
./.vim_SO/README.txt
./.vim_SO/.git
./.vim_SO/.git/objects
./.vim_SO/.git/objects/pack
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.idx
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.pack
./.vim_SO/.git/objects/info
./.vim_SO/.git/refs
./.vim_SO/.git/refs/tags
...
Zastosowanie -I{}
Nie należy stosować tego podejścia, ponieważ uruchomiono następującą konstrukcję polecenia:
$ find -print0 ... | xargs -I{} -0 ...
niejawnie włącza się do tych przełączników xargs
, -x
a -L 1
. W -L 1
konfiguruje xargs
tak, że dzwoni polecenia chcesz go uruchomić poprzez pliki w jednym modzie.
To przeczy celowi użycia xargs
tutaj, ponieważ jeśli dasz mu 1000 plików, uruchomi to mv
polecenie 1000 razy.
Więc jakiego podejścia powinienem użyć?
Możesz to zrobić za pomocą xargs:
$ find /foot/bar/ -name '*.mp4' -print0 | xargs -0 mv -t /some/path
Lub po prostu znajdź to wszystko:
$ find /foot/bar/ -name '*.mp4' -exec mv -t /some/path {} +
"This approach shouldn't be used"
które podejście należy zastosować? Czy"find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir'"
byłoby lepszym rozwiązaniem? Jeśli tak, to w jaki sposób będziexargs
wiedzieć w tym przypadku, gdy wmv
komendzie do paszy w argumentach, że dostaje od rury? (czy zawsze umieszcza je na końcu?)find ... -exec ...
lepszy sposób lub jeśli chcesz używać też jest w porządku. Tak, zawsze stawia je na końcu. Właśnie dlatego ta metoda potrzebuje .xargs
find ... | xargs ... mv -t ...
-t
Opcja
-i
przyjmuje opcjonalny argument. Ponieważ wstawiłeś spację po-i
tej-i
opcji , nie było argumentu dla opcji i dlatego następna-0
nie była opcją,xargs
ale drugim z 6 operandów{} -0 mv -t /some/path {}
.Tylko z tą opcją
-i
xargs oczekiwał listy nazw plików oddzielonych znakiem nowej linii. Ponieważ prawdopodobnie nie było nowego wiersza na wejściu, xargs otrzymał coś, co wyglądało jak ogromna nazwa pliku (z osadzonymi bajtami zerowymi, ale xargs tego nie sprawdził). Ten pojedynczy ciąg zawierający całe wyjściefind
był dłuższy niż maksymalna długość wiersza poleceń, stąd błąd „linia poleceń za długa”.Twoje polecenie działałoby
-i{}
zamiast-i {}
. Alternatywnie, mógłbyś użyć-I {}
:-I
jest podobny do-i
, ale przyjmuje argument obowiązkowy, więc następny argument przekazany doxargs
jest używany jako argument-I
opcji. Następnie argument,-0
który jest interpretowany jako opcja, i tak dalej.Jednak nie powinieneś w ogóle używać
-I {}
. Korzystanie-I
ma trzy efekty:-I
wyłącza przetwarzanie ofert, co-0
już działa.-I
zmienia ciąg do zastąpienia, ale{}
jest wartością domyślną.-I
powoduje, że polecenie jest wykonywane osobno dla każdego rekordu wejściowego, co jest tutaj bezużyteczne, ponieważ twoje polecenie (mv -t
) jest specjalnie przeznaczone do obsługi wielu plików na jedno wywołanie.Albo upuść
-I
i-i
całkowicielub upuść xargs i użyj
-exec
:źródło
Spróbuj użyć bash dla pętli:
lub jeśli chcesz zobaczyć, co się dzieje:
źródło
Jeśli widzisz to podczas używania skorupy ryby .
Odnosi się to do tego, jak ryba rozwija łańcuch zastępczy
{}
Jeśli używasz ryb, musisz uciec z łańcucha zastępczego
\{\}
lub użyj innego ciągu zastępczego
źródło