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

ls -1 liste mes éléments comme suit:

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

Je veux quil soit répertorié sans le .png comme ceci:

foo bar foobar ... 

(le répertoire ne contient que des fichiers .png)

Quelquun peut-il me dire comment utiliser grep dans ce cas?

Objectif: jai un fichier texte où tous les noms sont répertoriés sans le extension. Je veux créer un script qui compare le fichier texte avec le dossier pour voir quel fichier est manquant.

Commentaires

  • Vous voulez être prudent avec une demande comme celle-ci. Linux na pas dextensions de nom de fichier. Linux a des noms de fichiers qui peuvent ou non inclure un .. Bien que la convention dise de nommer vos fichiers avec .png à la fin, il ny a aucune raison pour que je ne puisse ‘ avoir un fichier png nommé foo.zip ou my.picture.20160518 ou simplement mypic.
  • @hymie I sais, mais mes éléments dans ce dossier sont tous nommés avec .png à la fin.
  • Ce que ‘ est un  » extension « ? Cela ‘ ne fait pas partie de la dénomination des fichiers Unix; il ‘ est reporté de VMS / NT / Windows peu importe. Et vous, les jeunes, sortez de ma pelouse aussi 🙂
  • Que ‘ ne surestime pas cela. Le système dexploitation considère les extensions comme faisant simplement partie du nom de fichier, mais de nombreux programmes Unix y prêtent attention, du compilateur à linterface graphique. Le concept nest très certainement pas étranger à unix.
  • Il est généralement suggéré de éviter danalyser la sortie de ls et de canaliser la sortie de ls et find, principalement parce que la possibilité dencourir dans newline,` tab char dans le nom du fichier. Si le nom du fichier est The new art of working on .png\NEWLINE files and other formats, la plupart des solutions proposées créeront des problèmes.

Réponse

Vous navez besoin que du shell pour ce travail.

POSIXly:

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

Avec zsh:

print -rl -- *.png(:r) 

Commentaires

  • Là ‘ nest pas nécessaire de printf; echo ${f%.png} suffira.
  • @Conrad: utiliser echo a gagné ‘ t fonctionne correctement dans certains cas, si le nom du fichier commencer par un tiret ou contenir des séquences déchappement.
  • @DavidConrad: voir aussi unix.stackexchange.com/a/65819/38906
  • @DavidConrad De plus, je crois que printf est intégré, tout comme echo, quelquun me corrige si je ‘ me trompe

Réponse

ls -1 | sed -e "s/\.png$//" 

La commande sed supprime (cest-à-dire, il remplace par la chaîne vide) toute chaîne .png trouvée à la end de un nom de fichier.

Le . est échappé comme \. afin quil soit interprété par sed en tant que caractère littéral . plutôt que lexpression régulière . (ce qui signifie correspondre à nimporte quel ch aracter). $ est lancre de fin de ligne, donc il ne correspond pas à .png au milieu dun nom de fichier.

Commentaires

  • Je pense que lOP veut que toute extension soit supprimée, mais probablement seulement  » le dernier « . Alors peut-être que vous pouvez modifier votre bonne réponse avec: sed 's/\.[^.]*$//'
  • oui, cette expression rationnelle fonctionne dans ce cas … mais si lOP le souhaite, il doit le dire au lieu de dire spécifiquement quil  » le souhaite répertorié sans le .png  »
  • Le -1 nest pas nécessaire, étant la valeur par défaut ici.
  • @jlliagre Je suis daccord avec cas que le -1 doit être spécifié. Ce ‘ est uniquement la valeur par défaut lorsque le canal est activé, ce qui est une surprise cachée pour certains. Il est donc utile de le rendre explicite Je le fais également dans mes scripts afin de savoir quel genre de o utput I ‘ m attend.
  • Attention Dans le cas dun nom de fichier avec la clé (.png) avant un caractère de nouvelle ligne, vous effacerez même ce .png et pas seulement le dernier. Il vaut mieux éviter de pipe et analyser la sortie de ls, cela réserve souvent des surprises bien cachées … (quelques mots et références en plus dans la réponse).

Réponse

Si vous souhaitez simplement utiliser bash:

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

Vous devez 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 lordre dans vos fichiers PNG, vous pouvez facilement changer cela en:

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

Commentaires

  • ls -1 | sed ‘ s / .png // ‘ fonctionne très bien. Merci!
  • La solution find redirigée vers sed peut présenter des problèmes si vous trouvez un fichier avec la clé (.png) comme une partie du nom et juste avant un caractère de nouvelle ligne. Il vaut mieux éviter de pipe et danalyser la sortie de find ou ls, cela réserve souvent des surprises bien cachées … (quelques mots et références plus dans la réponse).
  • Remplacez probablement find par quelque chose comme echo dans le dernier exemple. On ne sait pas à quoi sert find et les résultats dépendent de la structure du répertoire (cest-à-dire si vous avez un répertoire files.png)
  • @BroSlow Mise à jour vers quelque chose de plus sensé.

Réponse

Une autre réponse très similaire (je suis surpris une variante particulière n’est pas encore apparue) est:

ls | sed -n "s/\.png$//p" 
  • Vous n’avez pas besoin du -1 ls, puisque ls suppose que si la sortie standard nest pas « ta borne (cest » un tube, dans ce cas).
  • loption -n pour sed signifie « ne pas » imprimer la ligne par défaut « 
  • loption /p à la fin de la substitution signifie … et afficher cette ligne si une substitution a été faite.

Le réseau leffet de cela est dimprimer uniquement les lignes qui se terminent par .png, avec le 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 que des fichiers .png.

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

Commentaires

  • Jaime le soin apporté vous aviez lhabitude décrire votre réponse. Cette solution présentera des problèmes avec les noms de fichiers, y compris les sauts de ligne , elle nimprimera pas la première partie du nom. Encore plus si elle est plus méchante avec la clé (.png) avant le caractère de nouvelle ligne: dans ce cas, vous imprimerez cette partie sans png, sans effacer uniquement la dernière partie. Il est souvent suggéré déviter danalyser (et de diriger) la sortie de ls car les problèmes peuvent être cachés là où vous ne pensez pas …
  • @Hastur You ‘ est correct , en principe, et la célèbre page sur don ‘ t parse ls répertorie dautres problèmes (et solutions) lors de la transmission de noms de fichiers pathologiques. Mais la meilleure façon de gérer cela est d éviter davoir des noms de fichiers pathologiques (doh!); et si vous pouvez ‘ t, ou si vous devez être robuste contre eux, alors utilisez find ou – peut-être mieux – utilisez un langage plus puissant que sh pour les gérer (le fait que sh peut faire tout ne ‘ t signifie que ‘ est le meilleur choix dans chaque cas). Le shell est dabord conçu pour être utilisable.
  • Je suis daccord, en principe, sur la convivialité, mais cette variante échoue lorsque vous avez un nom de fichier avec chaque nouvelle ligne à lintérieur. Cela peut facilement se passer inaperçu, par exemple, lorsque vous copiez et collez une ligne à partir dun pdf dans une interface graphique, donc vous ne pensez quà éviter les noms de fichiers pathologiques.
  • De plus à mon humble avis Il est ‘ facile de commencer à analyser ls, mais cela pose de futurs problèmes. Souvent, nous créons des scripts que nous utiliserons plus tard, quand nous oublierons déjà leur limite … (elle ‘ est humaine, elle ‘ est habituelle). Jai proposé un exemple de find (avec -exec et sans tuyau) même si je considère quune meilleure (car pure shell) répond à celle de cuonglm ‘ , solide et conforme à posix.
  • Cest à peu près ce que je ‘ faire si, pour une raison quelconque, je voulais supprimer la bande de .png suffixe dune liste de noms de fichiers.Je ne le mettrais pas ‘ dans un script; à la place, je ‘ d tapez simplement la commande à linvite du shell. Cela rappellerait que je ‘ m en supposant  » sain desprit  » noms de fichiers. Il y a beaucoup de choses que je ‘ faire dans une commande manuelle ponctuelle, quand je me sens libre de faire des hypothèses sur ce que ‘ s dans le répertoire actuel, que je ne ferais probablement pas ‘ dans un script qui pourrait être réutilisé dans un autre contexte.

Réponse

Jirais pour basename (en supposant limplémentation GNU):

basename --suffix=.png -- *.png 

Commentaires

  • Notez que si vous souhaitez lutiliser dans un tube, vous trouverez peut-être utile dutiliser le nom de base GNU ‘ s -z (ou --zero) pour produire une option séparée par NUL (au lieu de ).

Réponse

Vous ne pouvez utiliser que des commandes BASH pour faire cela (sans aucun outil externe).

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

Ceci est utile lorsque vous « êtes sans / usr / bin et fonctionne bien pour les noms de fichiers l ike this.is.image.png et pour toutes les extensions.

Réponse

Cela ne suffisait pas?

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

ou en général, ce

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

supprimera toutes les extensions

Commentaires

  • Cétait mais les autres solutions fonctionnent aussi.
  • Tous les systèmes Unix / Unix Like ont (ou devraient avoir) sed installés car il sagit dun utilitaire obligatoire par le standard.
  • En effet, mais ls le fait quand même sans cette option quand sa sortie nest pas un terminal, ce qui est le cas ici.
  • Avertissement ls -1 | sed 's/\.[a-z]*//g' échouera sil y a un nom de fichier comme Image.png.jpg.png coupant tout le temps la clé (.png). Sous Unix sont autorisés les noms de fichiers étranges comme The new art of working on .png?files and other formats.png? est un caractère de nouvelle ligne. Malheureusement, toutes les solutions qui vont simplement diriger / analyser la sortie ls seront encourues en proble ms gestion de tels cas …
  • Pourquoi le qualificatif g? Vous souhaitez supprimer \.png uniquement à la fin de la ligne, pas à chaque fois quelle apparaît.

Réponse

Il nest pas sûr danalyser ls ou de rediriger find [ 1 , 2 ]

Il nest pas sûr de analyser (et canaliser) la sortie de ls ou find, principalement parce quil est possible de trouver dans les noms de fichiers caractères non habituels comme le newline , le tab … Ici un cycle de shell pur fonctionnera [ cuonglm ] .
Même la commande find non diffusée avec loption -exec fonctionnera:

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 seulement ceux qui ne sont pas cachés. Avec find *.png -exec ... vous pouvez avoir un problème dans le cas où il y aurait un fichier nommé .png car find laura en option. Vous pouvez ajouter -maxdepth 0 pour éviter de descendre dans les répertoires nommés Dir_01.png ou find ./*.png -prune -exec ... lorsque maxdepth nest pas autorisé (merci Stéphane). Si vous voulez éviter de lister ces répertoires, vous devez ajouter loption -type f (qui exclurait également dautres types de fichiers non réguliers). Jetez un œil au man pour un panorama plus complet de toutes les options disponibles, et pensez à vérifier quand elles sont compatibles POSIX, pour une meilleure portabilité.

Quelques mots en plus

Il peut arriver, par exemple, que la copie du titre dun document et le collage dans le nom du fichier, une ou plusieurs nouvelles lignes se terminent dans le nom du fichier lui-même.Nous pouvons même être si malchanceux quun titre puisse 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éez 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 allez pipe la sortie de ls ou find la commande suivante naura aucun indice pour comprendre si la ligne actuelle provient dun nouveau nom de fichier ou si elle suit un caractère nouvelle ligne dans le nom de fichier précédent. Un nom méchant certes, mais toujours légal.

Un cycle de shell avec un shell Parameter-Expansion, ${parameter%word}, dans les deux la variante avec printf ou echo fonctionnera [ cuonglm ], [ Anthon1 ] .

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

Depuis la page de manuel de lextension des paramètres du shell [ 3 ]

$ {paramètre% word}
$ {paramètre %% word}

… le résultat de lexpansion est la valeur du paramètre avec le modèle correspondant le plus court (le cas %) ou le le motif correspondant le plus long (le cas %%) supprimé.

Commentaires

  • Aussi les résultats de votre find est un bit variable (par exemple sil existe un répertoire appelé files.png)
  • Cher @BroSlow, quand jai écrit la réponse ci-dessus I essayé 13 (toutes) des autres variantes présentes à ce moment-là, par ligne de commande, dans un script, lancé comme argument dun appel de shell. Faites de même et dites-moi sils se comportent comme vous le souhaitez. Jai fait mes tests avec bash 4.3.11, tiret 0.5.7-4, zsh (si nécessaire) 5.0.2. Nhésitez pas à lire ce message qui ajoute quelque chose de plus. Je suis daccord sur la note de tuyauterie la sortie de find, pour cela jai suggéré expressément -exec , et jai écrit dans le titre. :-).
  • Relisez le wiki à nouveau. Je pense toujours que vous devez canaliser dans votre exemple, puisque ‘ est ce que ‘ est discuté ici. Et pour la majorité des versions modernes de ls, il ny a aucun problème lorsque la sortie est redirigée ou redirigée, mais comme mentionné dans le wiki, cela peut ne pas fonctionner pour tous. La plupart ninséreront que le ? à la place des caractères spéciaux lorsque la sortie est envoyée au terminal. cest-à-dire Faites echo *.png | od -c et ls *.png | od -c. Le problème de nouvelle ligne nest pas un problème avec ls, il ‘ est un problème avec toute commande qui ne ‘ t null se termine des deux côtés du tuyau.
  • printf "${f%.png}\n" est faux. Le premier argument est le format, vous ne devriez pas ‘ utiliser des données variables. Peut même être considéré comme une vulnérabilité DoS (essayez avec un fichier %1000000000s.png par exemple).
  • Vous ‘ d besoin find ./*.png -prune -exec... ou vous ‘ avez des problèmes avec les noms de fichiers commençant par - (et les fichiers de tapez le répertoire, notez que -maxdepth nest pas portable)

Answer

Utilisez rev:

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

rev inverse tous les chaînes (lignes); vous coupez tout après le premier « . » et rev renverse le reste.

Si vous voulez grep « alma »:

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

Commentaires

  • Le -1 nest pas nécessaire, étant la valeur par défaut ici.
  • Ceci échoue mal sur un fichier nommé My.2016.Summer.Vacation.png
  • @DavidConrad my bad: / Jai corrigé en cut -f 2-
  • Maintenant cela fonctionne avec ce fichier mais pas encore avec un fichier avec .png et une nouvelle ligne juste après … Il est suggéré déviter danalyser ls car il adore bien cacher les surprises … 🙂

Réponse

Si je savais que le répertoire ne contenait que des fichiers avec .png comme extension, jaurais juste lancé: ls | awk -F. "{print $1}"

Cela renverra 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 

Commentaires

  • Malheureusement, il échouera sur tous les noms de fichiers avec plus dun ., comme Image.1.png et même ceux avec pas sympa noms , avec des caractères spéciaux à lintérieur. comme nouvelle ligne ou celle que vous utiliserez comme séparateur denregistrement (dentrée) dans awk, RS. Il est suggéré déviter danalyser la sortie de ls car il adore cacher les problèmes qui surviendront lorsque vous ne vous y attendez pas. Pour en savoir plus, consultez les références 1 ou 2 . BTW sympa lidée dutiliser awk … Jai mis quelques exemples dans une seule réponse.
  • Cest vrai, cependant, étant donné lexemple fourni par Colin, cela fonctionnerait très bien. Pour que cela fonctionne pour le cas que vous avez suggéré, je ‘ le changerai probablement en: [rsingh @ rule51 TESTDIR] $ ls | sed -e ‘ s / .png $ // ‘ 10 1 2 3 4 5 6 7 8 9 harry.the.bunny quoi .a.png.filename Je nessaye pas dêtre difficile, mais étant donné les besoins de Colin ‘, je ‘ ne sais pas ce que le problème pourrait entraîner analyser ls.
  • désolé … Je viens de réaliser que je nai ‘ afficher le répertoire avec les fichiers avant que sed ne modifie la sortie de ‘ ls ‘ [rsingh @ rule51 TESTDIR] $ ls 10.png 2.png 4.png 6.png 8.png harry.the.bunny. png 1.png 3.png 5.png 7.png 9.png whats.a.png.filename.png [rsingh @ rule51 TESTDIR] $ ls | sed -e ‘ s / .png $ // ‘ 10 1 2 3 4 5 6 7 8 9 harry.the.bunny quoi .a.png.filename
  • note1 vous devez échapper le . dans \. à lintérieur du sed -e 's/\.png$//', mais ainsi cela devient une réponse juste écrite. 🙁 note2 vous pouvez essayer dutiliser awk avec quelque chose comme ls | awk -F. '{if ($NF=="png") {for (i=1;i<NF-1;i++) printf("%s.", $i) ; printf $(NF-1)"\n"}}' … mais vous aurez toujours le problème quawk ne peut pas savoir si la ligne arrive suit ou non une nouvelle ligne dans le nom du fichier. Jai essayé de dire mieux dans ma réponse.
  • Merci Hastur, jai raté ça :). De plus, jai abandonné lutilisation de awk au profit de sed dans ce cas.

Réponse

en fonction de votre comment « Jai un fichier texte où tous les noms sont listés sans lextension. Je veux créer 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 linverse:

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) 

Réponse

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

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

Commentaires

  • en utilisant ls -l, comme vous le faites, donne les détails du fichier, ce nest pas ce que lOP a demandé about.

Réponse

Une simple ligne de shell (ksh, bash ou zsh; pas un tiret):

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}}"; } 

À utiliser comme:

ne jpg 

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

Réponse

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

Answer

Si vous avez accès à sed, cest mieux car cela supprimera la dernière extension de fichier, quelle quelle soit (png, jpg, tiff, etc …)

ls | sed -e "s/\..*$//" 

Commentaires

  • Interruptions pour les noms de fichiers tels que this.is.a.dotty.txt. Essayez plutôt s/\.[^.]*$//.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *