Bash: ls * sans regroupement de dossiers

12

Si je tape:

ls source/*

source/fonts:
fontello

source/images:
bg1.png                eng.png        fra.png   

J'obtiens la liste des fichiers, regroupés par nom de dossier. Comment puis-je simplement obtenir la liste des noms de fichiers?

ls source/*

source/fonts/fontello
source/images/bg1.png
source/images/eng.png
source/images/fra.png   

Merci

Augustin Riedinger
la source
Si c'est à des fins de script, vous voudrez peut-être voir mywiki.wooledge.org/ParsingLs . (Cela dit, il existe également des moyens d'utiliser findmal; en particulier, si vous courez for file in $(find ...), vous en avez frappé un).
Charles Duffy

Réponses:

13

Cela ne semble pas possible sans modification de la sortie, mais voici une alternative simple:

find source/ -type f

Ou (spécifique à GNU find), pour obtenir uniquement des fichiers en profondeur dans votre question:

find source/ -type f -mindepth 2 -maxdepth 2

(ou si vous voulez des répertoires comme lsvous donne, supprimez -type f)

maxxvw
la source
5

Vous pouvez simplement vous en tenir à ls si vous ajoutez des psychédéliques ( ls -d):

# mkdir test
# cd test
# mkdir A B C
# touch {A,B,C}/file*
# ls -d */*    
A/file  B/file  C/file
ikrabbe
la source
@Cthulhu ok mon exemple est trop court, si vous avez des dossiers dans A, B a / o C, -d permet d'afficher uniquement ce que vous avez sélectionné. En fait, je n'aime pas trouver et vous pouvez définir la profondeur par l'argument avec ls -d
ikrabbe
J'ai suggéré une modification à l'autre réponse pour limiter la profondeur.
o11c
@ o11c très bon, mais findest toujours une grosse bête.
ikrabbe
3

Vous pouvez être intéressé par «le pauvre find»:

shopt -s globstar

shopt -s s ÉTS l'option shell nommé (s). L' globstaroption est définie comme suit dans bash (1) :

S'il est défini, le modèle **utilisé dans un contexte d'expansion de nom de fichier / chemin correspondra à un fichier [sic] et à zéro ou plusieurs répertoires et sous-répertoires. Si le modèle est suivi de a /, seuls les répertoires et sous-répertoires correspondent.

Donc, après avoir terminé shopt -s globstar, l'une des commandes suivantes:

ls -d1 - source / **                  # Le caractère après le «d» est le chiffre un. 
ls -d - source / ** | cat             # ie, il écrira cela dans un tube vers n'importe quelle commande. 
printf "% s \ n" source / **

produira la sortie:

source/
source/fonts
source/fonts/fontello
source/images
source/images/bg1.png
source/images/eng.png
source/images/fra.png

Malheureusement, cela inclut également les noms de répertoire. Cela pourrait vous aider un peu à savoir que

printf "%s\n" source/**/

produira la sortie:

source/
source/fonts
source/images

c'est-à-dire uniquement les noms de répertoire. Vous pouvez rediriger la sortie de l' un des premier jeu de commandes à un fichier, rediriger la sortie de ce qui précède à un second fichier, puis utiliser comm, diffou quelque chose de similaire, pour soustraire le second fichier à partir du premier, ne laissant que la plaine fichiers (non-répertoires). Mais ne fais pas ça.

Une autre approche (ce n'est pas beaucoup mieux) est

ls -d --file-type -- source/** | grep -v '/$'

L' --file-typeoption indique lsd'afficher un / à la fin de chaque nom de répertoire (et d'autres caractères à la fin d'autres types de fichiers (spéciaux)), comme ceci:

source //                             # Ajout d'une 
source supplémentaire / polices /                        # Ajout d'une
source / polices / fontello
source / images /                       # Ajout d'un
source / images / bg1.png
source / images / eng.png
source / images / fra.png

puis le grep -v '/$'supprime les lignes qui se terminent par /; c'est-à-dire les noms de répertoire. Malheureusement, l' --file-typeoption n'est pas spécifiée par POSIX . Si votre version de lsne la prend pas en charge, utilisez -F. C'est comme --file-type sauf qu'il affiche également un *à la fin des noms des fichiers exécutables, ce que certaines personnes trouvent ennuyeux. Vous pouvez les éliminer avec sed:

ls -dF -- source/** | sed -e '/\/$/d' -e 's/\*$//'

Si vous voulez faire quelque chose avec tous les fichiers (et seulement les fichiers), vous pouvez le faire

pour f dans la source / **
faire
    si [-f "$ f"]
    ensuite
        Insérez ici les commandes à appliquer aux fichiers simples.
    Fi
terminé

Remarques:

  • Quand lsest sorti sur un terminal, et qu'il n'est pas en mode -l( l ong), il écrit plusieurs noms par ligne (sauf si les noms sont très longs). Vous pouvez le forcer à écrire un nom par ligne en spécifiant -1(un) ou en redirigeant la sortie vers un fichier ou un canal.
  • Vous n'avez probablement pas vraiment besoin de --dans les lscommandes car vous listez un répertoire dont vous avez créé le contenu. Vous devez l'utiliser lors de l'inscription *dans un répertoire inconnu, comme protection contre les noms de fichiers commençant par -.
  • N'essayez pas d'analyser la sortie de ls.
  • L' globstaroption shell ne semble pas être définie par POSIX. (En fait, je ne suis pas sûr que POSIX reconnaisse les options du shell.) Bien qu'il semble s'agir d'un bashisme, méfiez-vous - il pourrait ne pas être présent dans toutes les versions de bash.
  • Si fontsou imagesa des sous-répertoires, **les énumérera tous, récursivement, tout en bas. Une façon (quelque peu maladroite et peu fiable) de limiter la profondeur est

    ls -d --file-type -- source/** | grep -v '\(/.*\)\{3\}'
    

    qui supprime les lignes contenant trois caractères ou plus /.

Scott
la source