web-dev-qa-db-fra.com

'ls -1': comment lister les noms de fichiers sans extension

ls -1 répertorie mes éléments comme suit:

foo.png
bar.png
foobar.png
...

Je le veux répertorié sans le .png ainsi:

foo
bar
foobar
...

(le répertoire contient uniquement .png des dossiers)

Quelqu'un peut-il me dire comment utiliser grep dans ce cas?

Objectif: J'ai un fichier texte où tous les noms sont répertoriés sans l'extension. Je veux faire un script qui compare le fichier texte avec le dossier pour voir quel fichier est manquant.

27
Colin

Vous n'avez besoin que du Shell pour ce travail.

POSIX:

for f in *.png; do
    printf '%s\n' "${f%.png}"
done

Avec zsh:

print -rl -- *.png(:r)
45
cuonglm
ls -1 | sed -e 's/\.png$//'

La commande sed supprime (c'est-à-dire qu'elle remplace par la chaîne vide) toute chaîne .png trouvé à la fin d'un nom de fichier.

Le . est échappé par \. pour qu'il soit interprété par sed comme un littéral . caractère plutôt que l'expression rationnelle . (ce qui signifie correspondre à n'importe quel caractère). Le $ est l'ancre de fin de ligne, donc elle ne correspond pas à .png au milieu d'un nom de fichier.

38
cas

Si vous souhaitez simplement utiliser bash:

for i in *; do echo "${i%.png}"; done

Vous devriez atteindre grep lorsque vous essayez de trouver des correspondances, pas pour supprimer/remplacer cela sed est plus approprié:

find . -maxdepth 1 -name "*.png"  | sed 's/\.png$//'

Une fois que vous avez décidé de créer des sous-répertoires pour mettre de l'ordre dans vos fichiers PNG, vous pouvez facilement changer cela en:

find . -name "*.png"  | sed 's/\.png$//'
16
Anthon

J'irais pour basename (en supposant que GNU implémentation):

basename --suffix=.png -- *.png
13
hennr

Une autre réponse très similaire (je suis surpris que cette variante particulière ne soit pas encore apparue) est:

ls | sed -n 's/\.png$//p'
  • Vous n'avez pas besoin du -1 option à ls, puisque ls suppose que si la sortie standard n'est pas un terminal (c'est un tube, dans ce cas).
  • le -n option à sed signifie "ne pas imprimer la ligne par défaut"
  • le /p option à la fin de la substitution signifie "... et imprimez cette ligne si une substitution a été effectuée".

L'effet net de cela est d'imprimer uniquement les lignes qui se terminent par .png, avec le .png supprimé. Autrement dit, cela répond également à la légère généralisation de la question du PO, où le répertoire ne contient pas seulement .png des dossiers.

Le sed -n la technique est souvent utile dans les cas où vous pourriez autrement utiliser grep + sed.

12
Norman Gray

Vous pouvez utiliser uniquement des commandes BASH pour ce faire (sans aucun outil externe).

for file in *; do echo "${file%.*}"; done 

C'est utile lorsque vous êtes sans/usr/bin et fonctionne bien pour les noms de fichiers comme this.is.image.png et pour toutes les extensions.

Il n'est pas sûr d'analyser ls ou de diriger find[ 1 , 2 ]

Il n'est pas sûr d'analyser (et de diriger) la sortie de ls ou find, principalement parce qu'il est possible de trouver dans le noms de fichiers des caractères non habituels comme le newline, le tab ... Ici un cycle Shell pur fonctionnera[ cuonglm ].
Même la commande find non canalisée avec l'option -exec marchera:

find ./*.png  -exec  basename {} .png  \;

Mises à jour/notes : vous pouvez utiliser find . pour rechercher même les fichiers cachés, ou find ./*.png pour obtenir uniquement ceux qui ne sont pas cachés. Avec find *.png -exec ... vous pouvez avoir un problème dans le cas où il y avait un fichier nommé .png parce que find l'obtiendra en option. Vous pouvez ajouter -maxdepth 0 pour éviter de descendre dans des répertoires nommés Dir_01.png, ou find ./*.png -Prune -exec ... quand maxdepth n'est pas autorisé (merci Stéphane). Si vous voulez éviter de lister ces répertoires, vous devez ajouter l'option -type f (ce qui exclurait également d'autres types de fichiers non réguliers). Jetez un œil à man pour un panorama plus complet de toutes les options disponibles, et n'oubliez pas de vérifier quand elles sont conformes POSIX, pour une meilleure portabilité.

Quelques mots de plus

Il peut arriver, par exemple, qu'en copiant le titre d'un document et en le collant dans le nom de fichier, une ou plusieurs nouvelles lignes se terminent dans le nom de fichier lui-même. Nous pouvons même être si malchanceux qu'un titre peut contenir même la clé que nous devons utiliser juste avant une nouvelle ligne:

The new art of working on .png
files and other formats.

Si vous voulez tester, vous pouvez créer des noms de fichiers comme celui-ci avec les commandes

touch "A file with two lines"$'\n'"and This is the second.png"
touch "The new art of working on .png"$'\n'"files and other formats.png"

Le simple /bin/ls *png affichera ? au lieu des caractères non imprimables

A file with two lines?and This is the second.png
The new art of working on .png?files and other formats.png

Dans tous les cas où vous dirigerez la sortie de ls ou find la commande suivante n'aura aucun indice pour comprendre si la ligne actuelle provient d'un nouveau nom de fichier ou si elle suit un caractère newline dans le précédent nom de fichier =. Un méchant nom en effet, mais toujours légal.

Un cycle Shell avec une extension des paramètres Shell, ${parameter%Word}, dans les deux variantes avec printf ou echo fonctionnera [ cuonglm ], [ Anthon1 ] .

for f in *.png; do printf "%s\n" "${f%.png}" ; done

À partir de la page de manuel de l'extension des paramètres du shell []

$ {paramètre% Word}
$ {paramètre %% Word}

... le résultat de l'expansion est la valeur du paramètre avec le motif de correspondance le plus court (le cas "%") ou le motif de correspondance le plus long (le cas "%%") supprimé.

6
Hastur

n'était-ce pas suffisant?

ls -1 | sed 's/\.png//g'

ou en général, ce

ls -1 | sed 's/\.[a-z]*//g'

supprimera toutes les extensions

5
Rohail Abbas

Utilisez rev:

ls -1 | rev | cut -f 2- -d "." | rev

rev inverse toutes les chaînes (lignes); vous coupez tout après le premier "." et rev inverse le reste.

Si vous voulez grep 'alma':

ls -1 | rev | cut -f 2- -d "." | rev | grep 'alma'
3
Tom Solid

Si je savais que le répertoire n'avait que des fichiers avec l'extension .png, j'aurais simplement exécuté: ls | awk -F. '{print $1}'

Cela retournera le premier "champ" pour tout ce qui contient un nom de fichier.extension.

Exemple:

[rsingh@rule51 TESTDIR]$ ls
10.png  1.png  2.png  3.png  4.png  5.png  6.png  7.png  8.png  9.png

[rsingh@rule51 TESTDIR]$ ls | awk -F. '{print $1}'
10
1
2
3
4
5
6
7
8
9
2
rsingh

selon votre commentaire "J'ai un fichier texte où tous les noms sont répertoriés sans l'extension. Je veux faire un script PHP qui compare le fichier texte avec le dossier pour voir quel fichier est manquant " :

for file in $(cat yourlist) ; do
  [ -f "${file}.png" ] || {
    echo "$file : listed in yourlist, but missing in the directory"
  }
done
#assumes that filenames have no space...
# otherwise use instead:
#  while IFS= read file ; do ...(same inner loop as above)... ; done < yourlist

et l'inverse:

for file in *.png ; do
  grep "^${file%.png}$" yourlist >/dev/null || {
    echo "$file: present in the directory but not listed in yourlist"
  }
done
#I assume there are no spaces/tabs/? before/after names in 'yourlist'. Change the script accordingly if there are some (or sanitize the list)
2
Olivier Dulac

Vous pouvez essayer le flux suivant awk la sortie de ls votre superateur est le "." et puisque tous vos fichiers auront name.png, vous imprimez la première colonne:
ls | awk -F"." '{print $1}'

1
igiannak

Une simple ligne Shell (ksh, bash ou zsh; pas dash):

set -- *.png; printf '%s\n' "${@%.png}"

Une fonction simple (de No Extension):

ne(){ set -- *.png; printf '%s\n' "${@%.png}"; }

Ou une fonction qui supprime toute extension donnée (png par défaut):

ne(){ ext=${1:-png}; set -- *."$ext"; printf '%s\n' "${@%.${ext}}"; }

Utilisé comme:

ne jpg

Si la sortie est un astérisque *, aucun fichier avec cette extension n'existe.

1
user79743

ls -l | sed 's/\.png$//'

Est la méthode la plus précise mise en évidence par @roaima. Sans échappé \.png fichiers nommés a_png.png serait répertorié comme: a_.

1
aphorise