2017-04-30 2 views
3

Je souhaite imprimer tous les noms de fichier de chaque fichier d'un répertoire dans un fichier .txt.Imprimer la liste des fichiers dans un répertoire vers un fichier texte (mais pas le fichier texte lui-même) depuis le terminal

Supposons que j'avais un répertoire avec 3 fichiers:

file1.txt 
file2.txt 
file3.txt 

et j'ai essayé d'utiliser ls > output.txt.

La chose est que quand j'ouvre output.txt je trouve cette liste:

file1.txt 
file2.txt 
file3.txt 
output.txt 

Est-il un moyen d'éviter d'imprimer le nom du fichier dans lequel je redirigeant la sortie? Ou mieux existe-t-il une commande capable d'imprimer tous les noms de fichiers de fichiers dans un répertoire sauf un?

+1

Y a-t-il une raison pour laquelle vous devez imprimer la sortie dans le même répertoire que les autres fichiers? – Jeremy

+2

@Jeremy C'est plus facile pour moi de travailler avec. Mais oui, je pourrais créer le fichier dans un autre répertoire en évitant complètement le problème. Je ne pensais pas à cela – jackscorrow

Répondre

5
printf '%s\n' * > output.txt 

Notez que cela suppose qu'il n'y a pas de fichier output.txt pré-existante - le cas échéant, supprimez-le en premier.

  • printf '%s\n' * utilise globbing (filename expansion) pour imprimer les noms de robustement tous les fichiers et sous-répertoires situés dans le répertoire courant, ligne par ligne.

  • englobement se avantoutput.txt est créé via une redirection de sortie > output.txt (ce qui arrive encore avant que la commande est exécutée , ce qui explique votre problème), de sorte que son nom est pas inclus dans la sortie.La globalisation évite également l'utilisation de ls, dont l'utilisation dans les scripts est generally discouraged.

1

En général, il n'est pas bon d'analyser la sortie de ls, en particulier lors de l'écriture de scripts de qualité de production qui doivent être en règle depuis longtemps. Voir cette page pour savoir pourquoi: Don't parse ls output

Dans votre exemple, output.txt est une partie de la production en ls > output.txt car shell organise la redirection (à sortie.txt) avant d'exécuter ls.

La façon la plus simple d'obtenir le bon comportement pour votre cas serait:

ls file*txt > output.txt # as long as you are looking for files named that way 

ou, stocker la sortie dans un fichier caché (ou dans un fichier normal dans un autre répertoire), puis déplacez-le vers le lieu final:

ls > .output.txt && mv .output.txt output.txt 

Une solution plus générique serait d'utiliser grep -v:

ls | grep -vFx output.txt > output.txt 

Ou, vous pouvez utiliser un tableau:

files=("$(ls)") 
printf '%s\n' "${files[@]}" > output.txt 
+2

Je pense que cela continue d'aller à l'encontre des noms de fichiers multilignes où l'une des lignes est 'output.txt' (c'est un cas exotique). Comme pour l'autre solution: Pourquoi ne pas simplement utiliser une variable chaîne au lieu d'un tableau à un seul élément? 'files =" ($ ls) "; printf '% s' "$ files"> output.txt' – melpomene

0

La façon la plus sûre, sans prendre quoi que ce soit sur les noms de fichiers, est d'utiliser des tableaux de bash (en mémoire) ou un fichier temporaire. Un fichier temporaire n'a pas besoin de mémoire, il peut donc être encore plus sûr. Quelque chose comme:

#!/bin/bash 
tmp=$(tempfile) 
ls > $tmp 
mv $tmp output.txt 
0

ls a une option ignore et nous pouvons aussi utiliser la commande find.

  • En utilisant ls avec option Ignore

    ls -I "output.txt" > output.txt 
    ls --ignore "output.txt" > output.txt 
    

-I, --ignore sont les mêmes. Cette option indique, comme dans la page de manuel, ne pas lister les entrées implicites correspondant au PATTERN du shell.

  • En utilisant find

    find \! -name "output.txt" > output.txt 
    

l'option -name dans find trouve des fichiers/répertoires dont le nom correspond au modèle. ! -name exclut dont le nom correspond au motif.

find \! -name "output.txt" -printf '%P\n' > output.txt 

% P bandes le chemin et donne les noms seulement.

+1

Vos commandes supposent l'utilisation des utilitaires _GNU_ (Linux) - veuillez clarifier ce prérequis dans votre réponse. Pour que les commandes 'find' soient équivalentes, vous (a) avez besoin de' -maxdepth 1' pour empêcher la récursion, et (b) vous devez trier la liste des noms de fichiers. – mklement0

+0

Je n'ai pas l'option ignorer sur ma machine. Je n'utilise pas Linux – jackscorrow