Für Dateien im Verzeichnis nur Echo-Dateiname (kein Pfad)

98

Wie gehe ich vor, um nur den Dateinamen einer Datei wiederzugeben, wenn ich ein Verzeichnis mit einer for-Schleife iteriere?

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

zieht den vollständigen Pfad mit dem Dateinamen. Ich möchte nur den Dateinamen.

Mechaflash
quelle

Antworten:

166

Wenn Sie eine native bashLösung wünschen

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

Das obige verwendet die Parametererweiterung, die der Shell eigen ist und keinen Aufruf einer externen Binärdatei wie zbasename

Könnte ich jedoch vorschlagen, nur zu verwenden find

find /home/user -type f -printf "%f\n"
SiegeX
quelle
9
Gute Antwort. Für diejenigen, die mehr über die Parametererweiterung erfahren
möchten
1
-printf: unbekannter Primär- oder Operator => unix.stackexchange.com/a/272493/72893
Nobita
2
Ziehen Sie in Betracht, ${file##*/}zu "${file##*/}"zu wechseln , um Dateinamen mit Leerzeichen zu unterstützen, z. B. "Mein Dateiname mit Leerzeichen.txt".
WinEunuuchs2Unix
echo "$ {file ## * /}" gibt eine leere Zeichenfolge zurück
Alessandro C
47

Verwenden Sie einfach basename:

echo `basename "$filename"`

Die Anführungszeichen werden benötigt, wenn $ filename zB Leerzeichen enthält.

Sean Bright
quelle
3
Besser die Parametererweiterung zu verwenden, erfordert keine Aufrufe von externen Binärdateien.
SiegeX
5
Übrigens ist `` veraltet. Besser zu verwenden $()wie Oli
SiegeX
1
Es tut uns leid, dass Sie diese alte Antwort kommentiert haben, aber der Basisname funktioniert bei Dateien mit Speicherplatz nicht richtig. Beispiel: pwd output : /test 1, basename $(pwd)output : test. Getestet unter OS X und Ubuntu Server (14.04). Native Bash-Lösung, wie von @SiegeX empfohlen, hat bei mir funktioniert.
Marko Grešak
@ MarkoGrešak Verwenden Sie basename "$(pwd)"stattdessen.
YoungFrog
@YoungFrog danke für die Eingabe, aber das war vor 9 Monaten. Es ist auch besser, die Variable zu $PWDverwenden, als den Befehl auszuführen.
Marko Grešak
15

Verwendung basename:

echo $(basename /foo/bar/stuff)
Oliver Charlesworth
quelle
Warum benutzt du echo? basenamedruckt bereits die Ergebnisse. echokann das Ergebnis sogar entstellen, wenn Sie die Unterschale nicht zitieren. Beispiel: echo $(basename path/with\ \ spaces)Druckt falsch with spaces(nur ein Leerzeichen).
Socowi
7

Ein anderer Ansatz ist das lsLesen der Dateiliste in einem Verzeichnis, um Ihnen das zu geben, was Sie möchten, dh "nur den / die Dateinamen". Im Gegensatz zum Lesen des vollständigen Dateipfads und anschließenden Extrahieren der Komponente "Dateiname" im Hauptteil der for-Schleife.

Beispiel unten, das Ihrem Original folgt:

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

Wenn Sie das Skript im selben Verzeichnis wie die Dateien ausführen, wird es einfach zu:

for filename in $(ls)
do
  echo $filename
done;
Ryan
quelle
1
lsEnthält alle Punktedateien, bei denen die *Erweiterung normalerweise nicht erfolgt. for f in $(...) ...Schlägt auch fehl, wenn ein Dateiname Leerzeichen enthält, es sei denn, Sie setzen IFS, kann fehlschlagen, wenn ein Dateiname ein glob-Zeichen enthält, es sei denn, Sie setzen -f / -o noglob, und je nach System oder Shell echokann dies fehlschlagen, wenn ein Dateiname Bindestrich + Buchstabe ist oder Backslash enthält. OTOH ls -1 /path/to/dirdruckt jeden Dateinamen für sich allein zuverlässig in eine Zeile, modulo den Unterschied zwischen den Punktedateien.
Dave_thompson_085
0

Wenn Sie nur Dateinamen möchten:

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

Weitere Informationen zum cutBefehl finden Sie hier .

josef
quelle