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.
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)
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.
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$//'
J'irais pour basename
(en supposant que GNU implémentation):
basename --suffix=.png -- *.png
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'
-1
option à ls
, puisque ls
suppose que si la sortie standard n'est pas un terminal (c'est un tube, dans ce cas).-n
option à sed
signifie "ne pas imprimer la ligne par défaut"/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.
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.
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é.
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é.
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
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'
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
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)
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}'
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.
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_
.