Pour les fichiers dans le répertoire, uniquement le nom du fichier (pas de chemin)

99

Comment puis-je faire écho uniquement au nom de fichier d'un fichier si j'itère un répertoire avec une boucle for?

for filename in /home/user/*
do
  echo $filename
done;

tirera le chemin complet avec le nom du fichier. Je veux juste le nom du fichier.

Méchaflash
la source

Réponses:

166

Si vous souhaitez une bashsolution native

for file in /home/user/*; do
  echo "${file##*/}"
done

Ce qui précède utilise l' expansion des paramètres qui est native du shell et ne nécessite pas d'appel à un binaire externe tel quebasename

Cependant, pourrais-je suggérer d'utiliser simplement find

find /home/user -type f -printf "%f\n"
SiegeX
la source
9
Bonne réponse. Pour ceux qui souhaitent en savoir plus sur l'expansion des paramètres: wiki.bash-hackers.org/syntax/pe#substring_removal
DougW
1
-printf: unknown primary or operator => unix.stackexchange.com/a/272493/72893
Nobita
2
Pensez à changer ${file##*/}pour "${file##*/}"prendre en charge les noms de fichiers avec des espaces, par exemple "Mon nom de fichier avec espaces.txt".
WinEunuuchs2Unix
echo "$ {file ## * /}" renvoie une chaîne vide
Alessandro C
48

Utilisez simplement basename:

echo `basename "$filename"`

Les guillemets sont nécessaires dans le cas où $ filename contient par exemple des espaces.

Sean Bright
la source
3
mieux utiliser l'expansion des paramètres, ne nécessite aucun appel à des binaires externes.
SiegeX
5
Btw, `` est obsolète. Mieux vaut utiliser $()comme Oli l'a fait
SiegeX
1
Désolé d'avoir commenté cette ancienne réponse, mais le nom de base ne fonctionnera pas correctement pour les fichiers avec de l'espace. Exemple: sortie PWD: /test 1, basename $(pwd)sortie: test. Testé sur OS X et Ubuntu Server (14.04). La solution native bash, comme le recommande @SiegeX, est ce qui a fonctionné pour moi.
Marko Grešak
@ MarkoGrešak Utilisez à la basename "$(pwd)"place.
YoungFrog
@YoungFrog merci pour la contribution, mais c'était il y a 9 mois. Il serait également préférable d'utiliser la variable $PWDau lieu d'exécuter la commande.
Marko Grešak
16

Utilisez basename:

echo $(basename /foo/bar/stuff)
Oliver Charlesworth
la source
Pourquoi utilisez-vous echo? basenameimprime déjà les résultats. echopeut même altérer le résultat si vous ne citez pas le sous-shell. Exemple: echo $(basename path/with\ \ spaces)imprime incorrectement with spaces(un seul espace).
Socowi
8

Une autre approche consiste à utiliser lslors de la lecture de la liste de fichiers dans un répertoire afin de vous donner ce que vous voulez, c'est-à-dire "juste le nom du fichier / s". Par opposition à la lecture du chemin complet du fichier, puis à l'extraction du composant "nom de fichier" dans le corps de la boucle for.

Exemple ci-dessous qui suit votre original:

for filename in $(ls /home/user/)
do
  echo $filename
done;

Si vous exécutez le script dans le même répertoire que les fichiers, il devient simplement:

for filename in $(ls)
do
  echo $filename
done;
Ryan
la source
1
lsinclut tous les fichiers dotfiles où l' *expansion ne fonctionne généralement pas. Échoue également for f in $(...) ...si un nom de fichier contient des espaces sauf si vous définissez IFS, peut échouer si un nom de fichier contient un caractère global sauf si vous définissez -f / -o noglob, et en fonction du système ou du shell echopeut échouer si un nom de fichier est un tiret + lettre ou contient une barre oblique inverse. OTOH ls -1 /path/to/dirimprime de manière fiable chaque nom de fichier sur une ligne, modulo la différence dotfiles.
dave_thompson_085
0

si vous voulez uniquement le nom de fichier:

for file in /home/user/*; do       
  f=$(echo "${file##*/}");
  filename=$(echo $f| cut  -d'.' -f 1); #file has extension, it return only filename
  echo $filename
done

pour plus d'informations sur la cutcommande, cliquez ici .

Josef
la source