J'ai une liste de fichiers séparés par des espaces dans un fichier list.txt
. Je voudrais les copier dans un nouveau dossier.
J'ai essayé de faire:
cp `cat list.txt` new_folder
Mais cela n'a pas fonctionné.
Comment ferais-tu ceci ?
Mise à jour:
Merci pour toutes vos réponses très intéressantes. Je n'ai pas demandé autant :)
Après avoir essayé la solution ci-dessus une deuxième fois, il semble que cp
l'aide à l'utilisation ait été imprimée car le dossier new_folder
n'existait pas encore! Désolé, cela semble être une erreur stupide ... Quand je crée le dossier avant, ça marche.
Cependant, j'ai beaucoup appris de toutes vos réponses et solutions, merci pour le temps que vous prenez pour les écrire.
Réponses:
Essayez d'utiliser xargs:
Mise à jour:
Je l'ai fait sur OS X qui a une version différente de celle des versions GNU / Linux. Ce
xargs
qui vient de GNU findutils n'a pas-J
mais il a-I
qui est similaire (comme l'a souligné Dennis Williamson dans un commentaire). La version OS X de xargs a les deux-I
et-J
qui ont des comportements légèrement différents - l'un ou l'autre fonctionnera pour cette question d'origine.la source
xargs
ne pas-J
qu'il a ce-I
qui semble faire la même chose. De quelle versionxargs
et de quel OS / distribution disposez-vous?xargs --version
renvoie un message d'erreur d'utilisation. Il s'agit probablement d'une version BSD de xargs. L'utilisation de-I
et-J
est subtilement différente. Je mettrai à jour ma réponse avec des exemples bien formatés.-J
et-I
:)Pas besoin du
cat
tout:Ou en utilisant des options longues:
Voici quelques versions shell. Notez que certaines variables ne sont pas entre guillemets ou que les
for
boucles sont utilisées spécifiquement parce que l'OP a spécifié que les noms de fichiers sont séparés par des espaces. Certaines de ces techniques ne fonctionneront pas pour une entrée de nom de fichier par ligne dans laquelle les noms de fichier contiennent des espaces blancs.Frapper:
ou
sh (ou Bash):
ou
ou
ou
la source
-t
nécessairexargs -a list.txt cp -t new_folder
?-t
c'est une option decp
. Il copie tous les arguments source dans le répertoire cible spécifié. Ici, il permet de spécifier la cible avant la source qui est ajoutée par laxargs
commande.J'ai eu une réponse gênante à propos de ce sujet plus tôt, mais la réponse de Denis m'a rappelé que j'avais raté la chose la plus élémentaire. J'ai donc supprimé ma réponse d'origine. Mais puisque personne n'a dit cette chose très basique, je pense que cela vaut la peine de la mettre ici.
La question d'origine est "J'ai un fichier texte avec une liste de noms de fichiers séparés par des espaces. Comment puis-je les copier dans un répertoire cible." Au début, cela peut sembler délicat ou compliqué, car vous pensez que vous devez en quelque sorte extraire les éléments du fichier d'une manière spécifique. Cependant, lorsque le shell traite une ligne de commande, la première chose qu'il fait est de séparer la liste des arguments en jetons et (voici le bit que personne n'a dit carrément) des espaces séparent les jetons . (Les nouvelles lignes séparent également les jetons, c'est pourquoi le test de Doug Harris avec une liste séparée par les nouvelles lignes a eu le même résultat.) Autrement dit, le shell attend et peut déjà gérer une liste séparée par des espaces.
Donc, tout ce que vous devez faire ici est de mettre la liste séparée par des espaces (que vous avez déjà) au bon endroit dans votre commande. Votre commande est une variation à ce sujet:
Le seul inconvénient est que vous souhaitez obtenir la liste des fichiers 1 à # à partir de votre fichier texte.
Comme Dennis le souligne dans son commentaire, votre tentative initiale (
cp
cat list.txtnew_folder
) aurait déjà dû fonctionner. Pourquoi? Parce que la commande internecat list.txt
est d'abord traitée par le shell et se développe enfile1 file2 file3...file#
, ce qui est exactement ce que le shell attend et veut à cette partie de la commande. Si cela ne fonctionnait pas, alors (1) vous aviez une faute de frappe ou (2) vos noms de fichiers étaient étranges (ils avaient des espaces ou d'autres caractères inhabituels).La raison pour laquelle toutes les réponses de Dennis fonctionnent est simplement qu'elles fournissent la liste de fichiers nécessaires
cp
pour travailler, en plaçant cette liste à sa place dans la commande entière. Encore une fois, la commande elle-même est structurée:Il est facile de voir comment tout cela se réunit dans cette version:
$()
oblige le shell à exécuter la commande entre parenthèses, puis à substituer sa sortie à ce point de la ligne la plus grande. Ensuite, le shell exécute la ligne dans son ensemble. Soit dit en passant,$()
est une version plus moderne de ce que vous faisiez déjà avec des backticks (`). Suivant:<
est un opérateur de redirection de fichiers. Il indique au shell de vider le contenu delist.txt
l'entrée standard. Puisque le$()
bit est traité en premier, voici ce qui se passe par étapes:cp $(<list.txt) new_folder
# split line into three tokens: cp, $(<list.txt), new_folder
cp file1 file2 file3...file# new_folder
# substitute result of $(<list.txt) into the larger command
De toute évidence, l'étape 2 est simplement la
cp
commande normale que vous vouliez.Je me rends compte que je bat beaucoup ce cheval (peut-être très mort), mais je pense que ça vaut le coup. Comprendre exactement comment le shell traite une commande peut vous aider à mieux l'écrire et à simplifier beaucoup. Il vous montrera également où les problèmes sont susceptibles de se cacher. Dans ce cas, par exemple, ma première question devrait vous concerner des noms de fichiers amusants ou une possible faute de frappe. Aucune acrobatie n'était nécessaire.
la source
--parents
drapeau. Vous pouvez le rendre verbeux avec-v
pour un enregistrement de ce qui a été copié. Si vous souhaitez conserver les autorisations, vous avez besoin du drapeau-a
ou-p
. -À- dire,cp --parents -av $(<list.txt) new_folder
. Tout cela en supposant que votre liste de fichiers est vraiment tous les fichiers, sinon vous pouvez également avoir besoin de l'-r
indicateur pour recurse.--parents
drapeau n'existe pas là-bas. Leur version (dérivée de BSD)cp
ne fournit que des options courtes, pas des options longues de style GNU. Pour un style BSDcp
, l'indicateur de copie récursive est en majuscules-R
et non en minuscules.