copyr plusieurs files dans plusieurs directorys

J'ai un problème à copyr de nombreux files dans différents directorys. Permettez-moi d'expliquer mieux:

Disons que j'ai ce qui suit dans un directory:

$ ls file1 file2 file3 file4 file5 dir1 dir2 dir3 

et je veux copyr chaque file * dans chaque dir * avec une seule command. J'ai essayé avec:

  echo dir{1..3} | xargs cp file{1..5} '{}' \; 

Mon intention était de dire à xargs de traiter chaque dir * de l'écho et de copyr tous les files dans l'input traitée mais cela et similaire ne fonctionnait pas. Je voudrais éviter l'utilisation d'un script parce que c'est une tâche que je dois répéter pour environ 20 directorys et les noms des files sont légèrement différents donc je préférerais modifier une command plutôt qu'un script.

echo dir[1-3] | xargs -r -n1 cp file[1-5]

Vous faites une petite erreur dans votre utilisation de xargs. Sans le paramètre -n, xargs ajoute tous les parameters en input à la command et echo dir{1..3} n'ajoute pas le return de chariot nécessaire entre chaque input, xargs considère donc le résultat comme un paramètre.

xargs a une option -n qui peut limiter le nombre d'inputs, et vous devez listr les directorys avec \ n ou \ 0 comme séparateur:

 find . -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 -n 1 cp file{1..5} 

La command find searchra tous les directorys du directory courant et utilisera \ 0 comme séparateur (ce qui fonctionne mieux si vous avez des directorys avec des espaces) et xargs utilise le séparateur \ 0 et lance la command à chaque fois avec un seul paramètre.

Quelque chose comme ce qui suit devrait fonctionner s'ils ont vraiment de tels noms:

 #!/bin/bash shopt -s nullglob for dir in dir*/; do cp file* "$dir" done 

Si vous souhaitez copyr tous les files dans tous les directorys, peu importe leur nom:

 #!/bin/bash shopt -s nullglob dotglob for dir in */; do for file in *; do [[ -f $file ]] && cp "$file" "$dir" done done 

Tu y es presque. Vous devez exécuter une command cp distincte pour chaque directory de destination, car cp ne fait qu'une copy de chaque file source. Le but principal de xargs est d'exécuter une command sur plusieurs arguments, mais vous pouvez lui dire de passer un seul élément à la fois avec l'option -n . Aussi {} ; est la syntaxe de find … -exec ; vous n'avez pas besoin (et ne pouvez pas l'utiliser) avec xargs .

 echo dir{1..3} | xargs -n 1 cp file{1..5} 

Notez que cela ne fonctionne que si les noms de vos directorys ne contiennent aucun espace ni aucun caractère, car xargs n'a aucun moyen de dire que ces caractères font partie des noms de files et ne citent pas et ne séparent pas les files d'input. n'a pas un tel problème est d'utiliser une boucle de shell:

 for d in dirs{1..3}; do cp file{1..5} "$d" done 

Tout cela suppose que vous pouvez facilement distinguer entre les files et les directorys par leurs noms. Si vous ne le pouvez pas, vous pouvez faire correspondre les directorys en ajoutant un / à la fin; par exemple */ correspond à tous les directorys des directorys actuels, foo[0-9]*/ correspond à tous les directorys dont le nom commence par foo et un chiffre, etc. Il n'y a pas de façon similaire de faire correspondre uniquement des non-directorys si vous passez des directorys à cp sans argument pour lui dire d'effectuer une copy récursive, les directorys sont ignorés avec un message d'erreur.

 for d in */; do cp * "$d" done 

Dans zsh, vous pouvez utiliser les qualificateurs glob pour ne correspondre qu'à certains types de files.

 for d in *(/); do cp *(.) $d done