สำหรับไฟล์ในไดเร็กทอรีเฉพาะชื่อไฟล์ echo (ไม่มีพา ธ )


100

ฉันจะไปเกี่ยวกับการสะท้อนเฉพาะชื่อไฟล์ของไฟล์ได้อย่างไรหากฉันวนซ้ำไดเร็กทอรีด้วย for loop

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

จะดึงเส้นทางแบบเต็มพร้อมชื่อไฟล์ ฉันต้องการแค่ชื่อไฟล์

คำตอบ:


169

หากคุณต้องการbashโซลูชันดั้งเดิม

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

ข้างต้นใช้การขยายพารามิเตอร์ซึ่งเป็นของเชลล์และไม่ต้องการการเรียกใช้ไบนารีภายนอกเช่นbasename

อย่างไรก็ตามฉันขอแนะนำให้ใช้ไฟล์ find

find /home/user -type f -printf "%f\n"

10
คำตอบที่ดี. สำหรับผู้ที่สนใจเรียนรู้เพิ่มเติมเกี่ยวกับการขยายพารามิเตอร์: wiki.bash-hackers.org/syntax/pe#substring_removal
DougW

1
-printf: หลักที่ไม่รู้จักหรือตัวดำเนินการ => unix.stackexchange.com/a/272493/72893
Aurelio

2
พิจารณาเปลี่ยน${file##*/}เป็น"${file##*/}"เพื่อรองรับชื่อไฟล์ที่มีช่องว่างเช่น "My filename with spaces.txt"
WinEunuuchs2Unix

1
echo "$ {file ## * /}" ส่งคืนสตริงว่าง
Alessandro C

48

เพียงใช้basename:

echo `basename "$filename"`

จำเป็นต้องมีเครื่องหมายคำพูดในกรณีที่ $ filename มีช่องว่างเช่น


3
ดีกว่าที่จะใช้การขยายพารามิเตอร์ไม่จำเป็นต้องเรียกใช้ไบนารีภายนอก
SiegeX

5
Btw `` เลิกใช้แล้ว ใช้ดีกว่า$()เหมือนที่ Oli ทำ
SiegeX

1
ขออภัยที่แสดงความคิดเห็นเกี่ยวกับคำตอบเก่านี้ แต่ชื่อฐานจะทำงานไม่ถูกต้องสำหรับไฟล์ที่มีช่องว่าง ตัวอย่าง: การส่งออกรหัสผ่าน: /test 1, เอาท์พุท:basename $(pwd) testทดสอบบน OS X และ Ubuntu Server (14.04) วิธีแก้ปัญหาทุบตีแบบเนทีฟตามที่ @SiegeX แนะนำคือสิ่งที่ใช้ได้ผลสำหรับฉัน
Marko Grešak

@ MarkoGrešakใช้basename "$(pwd)"แทน
YoungFrog

@YoungFrog ขอบคุณสำหรับข้อมูล แต่นั่นคือ 9 เดือนที่แล้ว นอกจากนี้จะเป็นการดีกว่าถ้าใช้ตัวแปร$PWDแทนการรันคำสั่ง
Marko Grešak

16

ใช้basename:

echo $(basename /foo/bar/stuff)

ทำไมคุณถึงใช้echo? basenameพิมพ์ผลลัพธ์แล้ว echoอาจทำให้ผลลัพธ์ยุ่งเหยิงหากคุณไม่อ้างถึง subshell ตัวอย่าง: echo $(basename path/with\ \ spaces)พิมพ์ไม่ถูกต้องwith spaces(เว้นวรรคเดียว)
Socowi

8

อีกแนวทางหนึ่งคือการใช้ lsเมื่ออ่านรายชื่อไฟล์ภายในไดเร็กทอรีเพื่อให้สิ่งที่คุณต้องการคือ "เพียงแค่ชื่อไฟล์ / s" ตรงข้ามกับการอ่านพา ธ ไฟล์แบบเต็มจากนั้นแยกคอมโพเนนต์ "ชื่อไฟล์" ในเนื้อหาของ for loop

ตัวอย่างด้านล่างที่เป็นไปตามต้นฉบับของคุณ:

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

หากคุณเรียกใช้สคริปต์ในไดเร็กทอรีเดียวกับไฟล์มันจะกลายเป็น:

for filename in $(ls)
do
  echo $filename
done;

1
lsรวม dotfiles ใด ๆ ที่ส่วน*ขยายมักจะไม่มี นอกจากนี้จะfor f in $(...) ...ล้มเหลวหากชื่อไฟล์ใด ๆ มีช่องว่างเว้นแต่คุณจะตั้งค่า IFS อาจล้มเหลวหากชื่อไฟล์ใด ๆ มี glob char เว้นแต่คุณจะตั้งค่า -f / -o noglob และขึ้นอยู่กับระบบหรือเชลล์echoอาจล้มเหลวหากชื่อไฟล์ใด ๆ เป็นยัติภังค์ + ตัวอักษรหรือมีเครื่องหมายแบ็กสแลช OTOH เพียงแค่ls -1 /path/to/dirพิมพ์ชื่อไฟล์แต่ละชื่อบนบรรทัดได้อย่างน่าเชื่อถือโมดูโลความแตกต่างของ dotfiles
dave_thompson_085

0

หากคุณต้องการชื่อไฟล์เท่านั้น:

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

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับcutคำสั่งดูที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.