J'ai une liste de noms de fichiers dans un fichier appelé list_of_files.txt
.
Je souhaite copier le contenu de chaque fichier de cette liste dans un autre fichier appelé all_compounds.sdf
.
Comment dois-je faire cela à partir de la ligne de commande?
N'utilisez pas de substitution de commande simple pour obtenir les noms de fichiers (qui pourraient facilement se briser avec des espaces et d'autres caractères spéciaux). Utilisez quelque chose comme xargs
:
xargs -d '\n' -a list_of_files.txt cat > all_compounds.sdf
Ou une boucle while read
:
while IFS= read -r file; do cat "$file"; done < list_of_files.txt > all_compounds.sdf
Pour utiliser la substitution de commande en toute sécurité, définissez au moins IFS
uniquement sur la nouvelle ligne et désactivez le mode de substitution (développement de caractère générique):
(set -f; IFS=$'\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)
Les parenthèses environnantes ()
doivent être exécutées dans un sous-shell afin que votre Shell actuel ne soit pas affecté par ces modifications.
Manière rapide et sale ...
cat $(cat list_of_files.txt) >> all_compounds.sdf
Remarque: Cela ne fonctionne que si les noms de fichiers de votre liste se comportent très bien. Les choses se passeront mal si elles ont des espaces, des nouvelles lignes ou tout autre caractère ont une signification particulière pour Shell - utilisez cette réponse à la place pour des résultats fiables)
cat
con cat énate les fichiers. Il imprime également leur contenu.command2 $(command1)
, vous pouvez transmettre le résultat de command1
(cat list...
) à command2
(cat
), qui concatène les fichiers.Utilisez ensuite la redirection >>
pour envoyer la sortie dans un fichier au lieu de l’imprimer sur la sortie standard. Si vous voulez voir la sortie, utilisez plutôt tee
:
cat $(cat list_of_files.txt) | tee -a all_compounds.sdf
(J'ai utilisé >>
au lieu de >
et tee
avec le commutateur -a
au cas où votre fichier existe déjà - ceci est ajouté au fichier au lieu de l'écraser, s'il existe déjà)
Bien que GNU awk
soit un utilitaire de traitement de texte, il permet d'exécuter des commandes Shell externes via l'appel system()
. Nous pouvons utiliser cela à notre avantage comme ceci:
$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt
L'idée ici est simple: nous lisons le fichier ligne par ligne et, à partir de chaque ligne, nous créons une chaîne formatée cat "File name.txt"
, qui est ensuite transmise à system()
.
Et le voici en action:
$ ls
file1.txt file2.txt file3 with space.txt file_list.txt
$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt
Hi, I'm file2
Hi, I'm file1
Hi, I'm file3
Nous avons donc déjà effectué l'essentiel de la tâche: nous avons imprimé tous les fichiers de la liste. Le reste est simple: redirigez la sortie finale vers le fichier avec l’opérateur >
dans le fichier de synthèse.
awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt > output.txt