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
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 verssed
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 defind
ouls
, 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 commeecho
dans le dernier exemple. On ne sait pas à quoi sertfind
et les résultats dépendent de la structure du répertoire (cest-à-dire si vous avez un répertoirefiles.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
, puisquels
suppose que si la sortie standard nest pas « ta borne (cest » un tube, dans ce cas). - loption
-n
poursed
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 dels
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 quesh
pour les gérer (le fait quesh
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 defind
(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 commeImage.png.jpg.png
coupant tout le temps la clé (.png
). Sous Unix sont autorisés les noms de fichiers étranges commeThe new art of working on .png?files and other formats.png
où?
est un caractère de nouvelle ligne. Malheureusement, toutes les solutions qui vont simplement diriger / analyser la sortiels
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 defind
, 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 Faitesecho *.png | od -c
etls *.png | od -c
. Le problème de nouvelle ligne nest pas un problème avecls
, 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 danalyserls
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
.
, commeImage.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) dansawk
,RS
. Il est suggéré déviter danalyser la sortie dels
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 dused -e 's/\.png$//'
, mais ainsi cela devient une réponse juste écrite. 🙁 note2 vous pouvez essayer dutiliserawk
avec quelque chose commels | 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ôts/\.[^.]*$//
.
.
. 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
oumy.picture.20160518
ou simplementmypic
.ls
et de canaliser la sortie dels
etfind
, principalement parce que la possibilité dencourir dansnewline
,` tab char dans le nom du fichier. Si le nom du fichier estThe new art of working on .png\NEWLINE files and other formats
, la plupart des solutions proposées créeront des problèmes.