Comment répertorier un nom de fichier par ligne de sortie sous Linux?


229

J'utilise la ls -acommande pour obtenir les noms de fichiers dans un répertoire, mais la sortie est sur une seule ligne.

Comme ça:

.  ..  .bash_history  .ssh  updater_error_log.txt

J'ai besoin d'une alternative intégrée pour obtenir les noms de fichiers, chacun sur une nouvelle ligne, comme ceci:

.  
..  
.bash_history  
.ssh  
updater_error_log.txt

3
ls est destiné à afficher une liste pour la consommation humaine. Si vous utilisez ls à d'autres fins (comme, par exemple, pour obtenir une liste de fichiers dans un script à parcourir), vous utilisez très certainement le mauvais outil.
Juliano

2
@juliano - Il doit être consommé par un script python en fait. Pourquoi appelez-vous cela un mauvais outil?
fixxxer

1
@fixxer Au moment où vous dirigez lsvers python, lsun fichier par ligne sera généré, comme je l'ai expliqué dans ma réponse.
Peter G.

6
@fixxxer: Dans ce cas, vous l'utilisez à tort. Il formate la liste pour la sortie dans le terminal utilisateur. Il peut remplacer des caractères spéciaux dans le nom de fichier, il peut omettre des caractères qui ont une signification spéciale, etc ... En d'autres termes, ls formate une liste pour l'utilisateur. Vous voulez des noms de fichiers non formatés. Une raison particulière pour laquelle vous n'utilisez pas le module «glob» de python? docs.python.org/library/glob.html Il existe également «fnmatch», «dircache» et d'autres.
Juliano

@fixxer Avez-vous réellement effectué lsune sortie vers pythonet observé la sortie d'une seule ligne en python?
Peter G.

Réponses:


430

Utilisez l' -1option (notez que c'est un chiffre "un", pas une lettre minuscule "L"), comme ceci:

ls -1a

Mais d'abord, assurez-vous que vos lssoutiens -1. GNU coreutils (installé sur les systèmes Linux standard) et Solaris do; mais en cas de doute, utilisez man lsou ls --helpou consultez la documentation. Par exemple:

$ man ls
...
       -1     list one file per line.  Avoid '\n' with -q or -b

2
+1 Je ne connaissais pas -1 (-l oui (ell pas un)) Il apparaît dans la page de manuel mais je l'ai lu comme un ell tout le temps :)
slashmais

@slashmais - Ah, bon point - facile à confondre. J'ai clarifié dans la réponse.
Bert F

1
@dty: pour GNU, vous obtenez ceci documenté en ls --helpsortie ... toujours installé ;-)
Tony Delroy

3
Recherche sur Google linux ls one file per lineet c'était le meilleur article. Je ne peux pas croire à quel point la réponse choisie est prolixe ou que cette réponse a moins de votes que celle qui catalyse. ls -1ftw.
crantok

3
lsle -1comportement par défaut lorsque la sortie n'est pas connectée au terminal.
codeforester

132

Oui, vous pouvez facilement faire lssortir un nom de fichier par ligne:

ls -a | cat

Explication: La commande lsdétecte si la sortie est vers un terminal ou vers un fichier ou un canal et s'ajuste en conséquence.

Donc, si vous dirigez ls -avers python, cela devrait fonctionner sans aucune mesure spéciale.


2
Wow, c'est génial. L'avantage par rapport à la réponse acceptée - celle-ci fonctionne réellement sur le shell Android / adb - où se lstrouve juste une version allégée qui ne prend donc pas en charge-1
mkilmanas

Comment éviteriez-vous que les " .et .." fichiers apparaissent dans la sortie?
matanster

@matanster: Cela dépend, voulez-vous voir des fichiers dot? Sinon, supprimez simplement l'option -a.
Peter G.

29

Ls est conçu pour la consommation humaine et vous ne devez pas analyser sa sortie .

Dans les scripts shell, il existe quelques cas où l'analyse de la sortie de ls fonctionne est le moyen le plus simple d'obtenir l'effet souhaité. Étant donné que ls peut modifier les caractères non ASCII et contrôler les noms de fichiers, ces cas sont un sous-ensemble de ceux qui ne nécessitent pas l'obtention d'un nom de fichier ls.

En python, il n'y a absolument aucune raison d'invoquer ls. Python a toutes lsles fonctionnalités intégrées. Utilisez os.listdirpour lister le contenu d'un répertoire et os.statou ospour obtenir des métadonnées de fichier. D'autres fonctions des osmodules sont également susceptibles d'être pertinentes pour votre problème.


Si vous accédez à des fichiers distants via ssh, un moyen raisonnablement robuste de répertorier les noms de fichiers est via sftp:

echo ls -1 | sftp remote-site:dir

Cela imprime un nom de fichier par ligne et, contrairement à l' lsutilitaire, sftpne modifie pas les caractères non imprimables. Vous ne pourrez toujours pas répertorier de manière fiable les répertoires dans lesquels un nom de fichier contient une nouvelle ligne, mais cela est rarement fait (rappelez-vous qu'il s'agit d'un problème de sécurité potentiel, pas d'un problème d'utilisation).

En python (attention aux métacaractères shell doivent être des échappements remote_dir):

command_line = "echo ls -1 | sftp " + remote_site + ":" + remote_dir
remote_files = os.popen(command_line).read().split("\n")

Pour des interactions plus complexes, recherchez le mode batch de sftp dans la documentation.

Sur certains systèmes (Linux, Mac OS X, peut-être d'autres unités, mais certainement pas Windows), une approche différente consiste à monter un système de fichiers distant via ssh avec sshfs , puis à travailler localement.


Je suis connecté via SSH à la machine distante. Je n'ai trouvé aucun moyen d'exécuter une fonction python comme os.listdir sur la machine distante sur une seule ligne. D'où cette question. Je ne veux pas écrire de script pour simplement lister les fichiers. Existe-t-il un autre moyen de contourner ce problème?
fixxxer

@fixxxer: ssh change la situation, c'est le genre de choses que vous auriez dû mentionner dans votre question d'origine! Je pense que sftp est approprié pour votre cas d'utilisation.
Gilles 'SO- arrête d'être méchant'

Je suis désolé pour la confusion. Puis-je également insérer le mot de passe dans la "ligne de commande"?
fixxxer

@fixxxer: Je ne sais pas, les auteurs de ssh froncent les sourcils sur les mots de passe stockés en texte brut et ont tendance à ne pas rendre cela facile. Vous devez vraiment configurer l'authentification par clé (il existe de nombreux didacticiels sur le Web et des questions sur superuser.com à ce sujet).
Gilles 'SO- arrête d'être méchant'

11

vous pouvez utiliser ls -1

ls -l fera également le travail


La première réponse mentionne déjà les choses exactes que vous avez dites. aussi la question dit spécifiquement ls -lne devrait pas être utilisée.
DevX

2

Facile, tant que vos noms de fichiers n'incluent pas de nouvelles lignes:

find . -maxdepth 1

Si vous redirigez ceci dans une autre commande, vous devriez probablement préférer séparer vos noms de fichiers par des octets nuls, plutôt que des sauts de ligne, car les octets nuls ne peuvent pas apparaître dans un nom de fichier (mais les sauts de ligne peuvent le faire):

find . -maxdepth 1 -print0

L'impression sur un terminal s'affichera probablement sur une seule ligne, car les octets nuls ne sont normalement pas imprimés. Certains programmes peuvent nécessiter une option spécifique pour gérer les entrées délimitées par des valeurs nulles, telles que sort's -z. De la même manière, votre propre script devrait en tenir compte.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.