Existe-t-il une option pour “ls” qui limite les caractères de nom de fichier?

question de syntaxe. Si j’ai un certain nombre de sous-répertoires dans un répertoire cible et que je veux afficher les noms des sous-titres dans un fichier texte, je peux facilement exécuter:

ls > filelist.txt 

sur la cible. Mais disons que tous mes sous-marins sont nommés avec un préfixe de 7 caractères comme:

 JR-5426_mydir JR-5487_mydir2 JR-5517_mydir3 ... 

et je veux juste les préfixes. Existe-t-il une option pour “ls” qui ne produira que n caractères par ligne?

Non, vous utilisez la commande cut :

 ls | cut -c1-7 

Ne pas utiliser ls dans un contexte programmatique; il devrait être utilisé ssortingctement pour la présentation aux humains – ParsingLs donne des détails sur pourquoi.

Sur Bash 4.0 ou version ultérieure, la liste ci-dessous fournit une liste dédupliquée de préfixes de nom de fichier:

 declare -A prefixes_seen=( ) # create an associative array -- aka "hash" or "map" for file in *; do # iterate over all non-hidden directory ensortinges prefixes_seen[${file:0:2}]=1 # add the first two chars of each as a key in the map done printf '%s\n' "${!prefixes_seen[@]}" # print all keys in the map separated by newlines 

Cela dit, si au lieu de vouloir un préfixe à 2 caractères, vous voulez tout avant le premier, vous pouvez écrire quelque chose de plus propre:

 declare -A prefixes_seen=( ) for file in *-*; do prefixes_seen[${file%%-*}]=1 # "${file%%-*}" cuts off "$file" at the first dash done printf '%s\n' "${!prefixes_seen[@]}" 

… et si vous ne vous souciez pas de la déduplication:

 for file in *-*; do printf '%s\n' "${file%%-*}" done 

… ou à la règle des deux caractères:

 for file in *; do printf '%s\n' "${file:0:2}" done 

Cela dit, si vous essayez de le faire correctement, vous ne devriez pas utiliser de nouvelles lignes pour séparer les listes de caractères de nom de fichier, car les nouvelles lignes sont valides dans les noms de fichiers sur les systèmes de fichiers POSIX. Pensez à un fichier nommé f$'\n'oobar – c’est-à-dire avec une nouvelle ligne littérale dans le deuxième caractère; le code écrit négligemment verrait f comme un préfixe et oo comme second, de ce seul nom. Itérer sur les préfixes de tableaux associatifs, comme cela est fait pour les réponses dédupliquées, est plus sûr dans ce cas, car il ne repose sur aucun caractère délimiteur.

Démontrer la différence – si au lieu d’écrire

 printf '%s\n' "${!prefixes_seen[@]}" 

tu as écrit

 printf '%q\n' "${!prefixes_seen[@]}" 

il émettrait le préfixe du fichier hypothétique f$'\n'oobar comme

 $'f\n' 

au lieu de

 f 

… avec une ligne supplémentaire en dessous.


Si vous voulez passer des listes de noms de fichiers (ou, comme ici, préfixes de noms de fichiers) entre les programmes, le moyen le plus sûr est de délimiter les éléments par NUL – car les NUL sont le seul caractère Chemin UNIX. (Un nom de fichier ne peut pas non plus contenir / , mais un chemin peut évidemment l’être).

Une liste délimitée par NUL peut être écrite comme suit:

 printf '%s\0' "${!prefixes_seen[@]}" 

… et relire dans une structure de données identique à la réception (si le code de réception est écrit en bash) comme ceci:

 declare -A prefixes_seen=( ) while IFS= read -r -d '' prefix; do prefixes_seen[$prefix]=1 done