Đối với các tệp trong thư mục, chỉ echo tên tệp (không có đường dẫn)


98

Làm cách nào để chỉ lặp lại tên tệp của tệp nếu tôi lặp lại thư mục với vòng lặp for?

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

sẽ kéo đường dẫn đầy đủ với tên tệp. Tôi chỉ muốn tên tệp.

Câu trả lời:


166

Nếu bạn muốn một bashgiải pháp gốc

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

Ở trên sử dụng Mở rộng tham số có nguồn gốc từ trình bao và không yêu cầu lệnh gọi đến tệp nhị phân bên ngoài, chẳng hạn nhưbasename

Tuy nhiên, tôi có thể đề nghị chỉ sử dụng find

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

9
Câu trả lời tốt. Đối với những người quan tâm đến việc tìm hiểu thêm về việc mở rộng tham số: wiki.bash-hackers.org/syntax/pe#substring_removal
DougW

1
-printf: chính hoặc toán tử không xác định => unix.stackexchange.com/a/272493/72893
Nobita

2
Cân nhắc thay đổi ${file##*/}để "${file##*/}"hỗ trợ tên tệp có dấu cách, ví dụ: "Tên tệp của tôi có dấu cách.txt".
WinEunuuchs2Unix

echo "$ {file ## * /}" trả về một chuỗi trống
Alessandro C

47

Chỉ cần sử dụng basename:

echo `basename "$filename"`

Dấu ngoặc kép là cần thiết trong trường hợp $ filename chứa khoảng trắng, ví dụ.


3
tốt hơn để sử dụng mở rộng tham số, không yêu cầu lệnh gọi đến mã nhị phân bên ngoài.
SiegeX

5
Btw, `` không được dùng nữa. Tốt hơn để sử dụng $()như Oli đã làm
SiegeX

1
Xin lỗi vì đã nhận xét về câu trả lời cũ này, nhưng tên cơ sở sẽ không hoạt động chính xác cho các tệp có dung lượng. Ví dụ: sản lượng pwd: /test 1, basename $(pwd)đầu ra: test. Đã thử nghiệm trên OS X và Ubuntu Server (14.04). Giải pháp bash gốc, như @SiegeX đề xuất, là giải pháp phù hợp với tôi.
Marko Grešak

@ MarkoGrešak Sử dụng basename "$(pwd)"thay thế.
YoungFrog

@YoungFrog cảm ơn bạn đã đóng góp ý kiến, nhưng đó là cách đây 9 tháng. Ngoài ra, sẽ tốt hơn nếu sử dụng biến $PWDthay vì chạy lệnh.
Marko Grešak

15

Sử dụng basename:

echo $(basename /foo/bar/stuff)

Tại sao bạn sử dụng echo? basenameđã in kết quả. echothậm chí có thể làm hỏng kết quả nếu bạn không trích dẫn vỏ con. Ví dụ: echo $(basename path/with\ \ spaces)in sai with spaces(chỉ một khoảng trắng).
Socowi

7

Một cách tiếp cận khác là sử dụng lskhi đọc danh sách tệp trong một thư mục để cung cấp cho bạn những gì bạn muốn, tức là "chỉ tên tệp / s". Trái ngược với việc đọc đường dẫn tệp đầy đủ và sau đó giải nén thành phần "tên tệp" trong phần thân của vòng lặp for.

Ví dụ bên dưới theo bản gốc của bạn:

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

Nếu bạn đang chạy tập lệnh trong cùng một thư mục với các tệp, thì nó chỉ đơn giản là:

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

1
lsbao gồm bất kỳ tệp dotfiles nào mà *việc mở rộng thường không. Cũng for f in $(...) ...không thành công nếu bất kỳ tên tệp nào chứa khoảng trắng trừ khi bạn đặt IFS, có thể không thành công nếu bất kỳ tên tệp nào chứa ký tự toàn cầu trừ khi bạn đặt -f / -o noglob và tùy thuộc vào hệ thống hoặc trình bao echocó thể không thành công nếu bất kỳ tên tệp nào là gạch nối + chữ cái hoặc chứa dấu gạch chéo ngược. OTOH hoàn ls -1 /path/to/dirtoàn tự in một cách đáng tin cậy từng tên tệp trên một dòng, mô đun hóa sự khác biệt dotfiles.
dave_thompson_085

0

nếu bạn chỉ muốn tên tệp:

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

để biết thêm thông tin về cutlệnh xem tại đây .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.