Eh bien, pour une chose, le -i
commutateur est obsolète:
-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.
Donc, quand j'ai changé votre commande en cela, cela a fonctionné:
$ find /foo/bar -name '*.mp4' -print0 | xargs -I{} -0 mv -t /some/path {}
Exemple
$ 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
...
Utilisation de -I{}
Cette approche ne doit pas être utilisée depuis l'exécution de cette construction de commande:
$ find -print0 ... | xargs -I{} -0 ...
active implicitement ces commutateurs vers xargs
, -x
et -L 1
. Le -L 1
configure xargs
pour qu'il appelle les commandes que vous souhaitez qu'il exécute les fichiers d'une seule manière.
Donc, cela va à l'encontre du but de l'utilisation xargs
ici, car si vous lui donnez 1000 fichiers, il va exécuter la mv
commande 1000 fois.
Alors, quelle approche dois-je utiliser alors?
Vous pouvez le faire en utilisant des xargs comme celui-ci:
$ find /foot/bar/ -name '*.mp4' -print0 | xargs -0 mv -t /some/path
Ou tout simplement trouver trouver tout faire:
$ find /foot/bar/ -name '*.mp4' -exec mv -t /some/path {} +
"This approach shouldn't be used"
quelle approche utiliser à la place? Serait"find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir'"
une meilleure solution? Si oui, comment nexargs
sait dans ce cas où lamv
commande à l' alimentation dans les arguments qu'il obtient de la conduite? (les place-t-il toujours en dernier?)find ... -exec ...
est une meilleure façon ou si vous voulez utiliserxargs
lefind ... | xargs ... mv -t ...
c'est bien aussi. Ouais ça les met toujours en dernier. C'est pourquoi cette méthode a besoin de-t
.L'option
-i
prend un argument facultatif. Puisque vous mettez un espace après-i
, il n'y avait aucun argument à l'-i
option et donc le suivant-0
n'était pas une option pourxargs
mais le deuxième des 6 opérandes{} -0 mv -t /some/path {}
.Avec seulement cette option
-i
, xargs attendait une liste de noms de fichiers séparés par des sauts de ligne. Puisqu'il n'y avait probablement pas de nouvelle ligne dans l'entrée, xargs a reçu ce qui ressemblait à un énorme nom de fichier (avec des octets nuls intégrés, mais xargs n'a pas vérifié cela). Cette chaîne unique contenant la sortie entière defind
était plus longue que la longueur de ligne de commande maximale, d'où l'erreur «ligne de commande trop longue».Votre commande aurait fonctionné avec
-i{}
au lieu de-i {}
. Alternativement, vous auriez pu utiliser-I {}
:-I
est similaire à-i
, mais prend un argument obligatoire, donc l'argument suivant passé àxargs
est utilisé comme argument de l'-I
option. Ensuite, l'argument qui suit-0
est interprété comme une option, etc.Cependant, vous ne devriez pas utiliser
-I {}
du tout. L'utilisation-I
a trois effets:-I
désactive le traitement des devis, ce qui est-0
déjà le cas.-I
change la chaîne à remplacer, mais{}
est la valeur par défaut.-I
entraîne l'exécution de la commande séparément pour chaque enregistrement d'entrée, ce qui est inutile ici car votre commande (mv -t
) est spécifiquement destinée à gérer plusieurs fichiers par appel.Soit laisser tomber
-I
et-i
tout à faitou supprimez xargs et utilisez
-exec
:la source
Essayez d'utiliser une boucle bash for:
ou si vous souhaitez voir ce qui se passe:
la source
Si vous voyez cela en utilisant la coquille de poisson .
Cela se rapporte à la façon dont le poisson étend la chaîne de remplacement
{}
Si vous utilisez du poisson, vous devez échapper à la chaîne de remplacement
\{\}
ou utilisez une chaîne de remplacement différente
la source