xargs -I zamienię-str różnicę opcji

16

Z mojego zrozumienia, poniższe słowa powinny oznaczać dokładnie to samo:

ls -1 | xargs file {}
ls -1 | xargs -I{} file {}

jeśli nie podano opcji -I, domyślnie jest to -I {}.

Chcę wyświetlić listę wszystkich plików w bieżącym katalogu i uruchomić filepolecenie na każdym z nich. Niektóre mają spacje w swoich nazwach. Zauważyłem jednak różnicę. Patrz poniżej:

$ ls -1
Hello World
$ ls -1 | xargs file {}
{}:    ERROR: cannot open `{}' (No such file or directory)
Hello: ERROR: cannot open `Hello' (No such file or directory)
World: ERROR: cannot open `World' (No such file or directory)
$ ls -1 | xargs -I{} file {}
Hello World: directory

Przy jawnym określeniu -I {} spacje w nazwach plików są traktowane zgodnie z oczekiwaniami.

foresightyj
źródło
3
„jeśli nie podano opcji -I, domyślnie jest to -I {}” - jest to niepoprawne, przynajmniej w przypadku GNU xargs.
jjlin
Rozumiem mój błąd. Należy określić albo xargs filealbo xargs -I{} file {}. Nie powinno być xargs file {}. Wydaje mi się, że kiedy wyraźnie podasz -I {}, bash potraktuje to jak file "Hello World". Bez -I {} jest traktowane jak file Hello World.
foresightyj
1
(1) Ta dyskusja ma niewiele wspólnego z powłoką (bash). (2) Dobrze, że znasz -1opcję ls, ale jest ona domyślnie włączona, gdy wyjściem lsjest plik lub potok, więc nie potrzebujesz go tutaj. (3) Mylisz się -Iz przestarzałą opcją -i(małe litery I). -ifoojest równoważne -Ifoo, ale zwykły -ijest równoważny -I{}. Ale użyj -I{}. (4) Jeśli naprawdę chcesz robić to, co mówisz, że chcesz robić, dlaczego po prostu nie powiedzieć file *?
Scott,
@Scott Moim pierwotnym zamiarem było napisanie `find. -nazwa „* .mov” | xargs -I {} plik {} `, aby znaleźć wszystkie pliki mov rekurencyjnie i uruchomić fileje na nich. Ale wymyśliłem prostszy przykład, używając ls. Masz rację. Do tego file *jest najlepszy.
foresightyj
1
znajdź ma -exec.
Cristian Ciupitu

Odpowiedzi:

20

-IWymaga określonej zastępczy. -iOpcja obejmie {}jest zastępczy. W tym miejscu znalazłem jakieś założenia {} man xargsprzynajmniej w Cygwin i CentOS.

Wywołanie xargs bez którejkolwiek z opcji nie wymaga symbolu zastępczego i po prostu dołącza STDIN na końcu argumentów.

Po prostu dodaj echodo swoich przykładów, aby zobaczyć, co robi xargs:

$ ls -1
Hello World/

Twój przykład mistakeny używa {}:

$ ls -1 | xargs echo file {}
file {} Hello World/

więc filecmd widzi argumenty {} Hello Worldi błędy.

Jeśli chcesz wyraźnie użyć {}w xargs:

$ ls -1 | xargs -i echo file {}
file Hello World/

Lub Bez symbolu zastępczego:

$ ls -1 | xargs echo file
file Hello World/

xargs, jak wspomniano powyżej, nie potrzebuje {}. Dołącza STDIN na końcu polecenia bez symbolu zastępczego. Użycie {} zwykle oznacza, że ​​chcesz, aby STDIN gdzieś w środku cmd był wykonywany, jak w:

$ ls -1 | xargs -i mv {} /path/to/someplace/.
johnnyB
źródło
To jest bardzo jasne. Chociaż twoja odpowiedź jest nieco spóźniona, ale przeczytanie jej naprawdę wzmacnia moje zrozumienie.
foresightyj