Câu trả lời:
Trong GNU findbạn có thể sử dụng -printftham số cho điều đó, ví dụ:
find /dir1 -type f -printf "%f\n"
-ocó độ ưu tiên thấp hơn hàm ý -a, vì vậy bạn sẽ thường muốn nhóm các -ođối số của mình )
Nếu tìm thấy của bạn không có tùy chọn -printf, bạn cũng có thể sử dụng tên cơ sở:
find ./dir1 -type f -exec basename {} \;
... {} ';'
Sử dụng -execdirtự động giữ tệp hiện tại {}, ví dụ:
find . -type f -execdir echo '{}' ';'
Bạn cũng có thể sử dụng $PWDthay vì .(trên một số hệ thống, nó sẽ không tạo thêm một dấu chấm ở phía trước).
Nếu bạn vẫn có thêm một dấu chấm, thay vào đó bạn có thể chạy:
find . -type f -execdir basename '{}' ';'
-execdir utility [argument ...] ;Chính
-execdirlà giống hệt với-execchính với ngoại lệ rằng tiện ích sẽ được thực thi từ thư mục chứa tệp hiện tại .
Khi được sử dụng +thay thế ;, sau đó {}được thay thế bằng càng nhiều tên đường dẫn càng tốt cho mỗi lần gọi tiện ích. Nói cách khác, nó sẽ in tất cả tên tệp trong một dòng.
./filenamethay vì filename. Tùy thuộc vào nhu cầu của bạn, nó có thể hoặc không thể tốt.
$PWDthay vì ..
Nếu bạn đang sử dụng GNU, hãy tìm
find . -type f -printf "%f\n"
Hoặc bạn có thể sử dụng ngôn ngữ lập trình như Ruby (1.9+)
$ ruby -e 'Dir["**/*"].each{|x| puts File.basename(x)}'
Nếu bạn thích một giải pháp bash (ít nhất 4)
shopt -s globstar
for file in **; do echo ${file##*/}; done
Nếu bạn chỉ muốn chạy một số hành động đối với tên tệp, việc sử dụng basenamecó thể khó khăn.
Ví dụ này:
find ~/clang+llvm-3.3/bin/ -type f -exec echo basename {} \;
sẽ chỉ echo tên cơ sở /my/found/path. Không phải những gì chúng ta muốn nếu chúng ta muốn thực hiện trên tên tệp.
Nhưng bạn có thể sau đó xargsđầu ra. ví dụ để giết các tệp trong một thư mục dựa trên tên trong một thư mục khác:
cd dirIwantToRMin;
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \; | xargs rm
find ~/clang+llvm-3.3/bin/ -type f -exec basename {} \;
-execvà -execdirlà chậm, xargslà vua.
$ alias f='time find /Applications -name "*.app" -type d -maxdepth 5'; \
f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l; \
f -print0 | xargs -0 basename | wc -l
139
0m01.17s real 0m00.20s user 0m00.93s system
139
0m01.16s real 0m00.20s user 0m00.92s system
139
0m01.05s real 0m00.17s user 0m00.85s system
139
0m00.93s real 0m00.17s user 0m00.85s system
139
0m00.88s real 0m00.12s user 0m00.75s system
xargssong song cũng giúp.
Đủ vui tôi không thể giải thích trường hợp cuối cùng xargsmà không có -n1. Nó cho kết quả chính xác và nhanh nhất¯\_(ツ)_/¯
( basenamechỉ mất 1 đối số đường dẫn nhưng xargssẽ gửi tất cả (thực tế là 5000) mà không có -n1. không hoạt động trên linux và openbsd, chỉ macOS ...)
Một số số lớn hơn từ hệ thống linux để xem cách -execdirgiúp, nhưng vẫn chậm hơn nhiều so với song song xargs:
$ alias f='time find /usr/ -maxdepth 5 -type d'
$ f -exec basename {} \; | wc -l; \
f -execdir echo {} \; | wc -l; \
f -print0 | xargs -0 -n1 basename | wc -l; \
f -print0 | xargs -0 -n1 -P 8 basename | wc -l
2358
3.63s real 0.10s user 0.41s system
2358
1.53s real 0.05s user 0.31s system
2358
1.30s real 0.03s user 0.21s system
2358
0.41s real 0.03s user 0.25s system
findnó -execdirtrở nên nhanh nhất vì việc tạo các quy trình mới là một hoạt động tương đối tốn kém.
Như những người khác đã chỉ ra, bạn có thể kết hợp findvà basename, nhưng theo mặc định basenamechương trình sẽ chỉ hoạt động trên một con đường tại một thời điểm, do đó thực thi sẽ phải được đưa ra một lần cho mỗi con đường (sử dụng một trong hai find ... -exechoặc find ... | xargs -n 1), có thể có khả năng bị chậm.
Nếu bạn sử dụng -atùy chọn trên basename, thì nó có thể chấp nhận nhiều tên tệp trong một lệnh gọi duy nhất, điều đó có nghĩa là bạn có thể sử dụng xargsmà không cần -n 1, để nhóm các đường dẫn lại với nhau thành một số lượng yêu cầu nhỏ hơn basename, sẽ hiệu quả hơn.
Thí dụ:
find /dir1 -type f -print0 | xargs -0 basename -a
Ở đây tôi đã bao gồm -print0và -0(nên được sử dụng cùng nhau), để đối phó với bất kỳ khoảng trắng nào bên trong tên của tệp và thư mục.
Đây là một so sánh thời gian, giữa xargs basename -avà xargs -n1 basenamecác phiên bản. (Để so sánh giống như so sánh, thời gian được báo cáo ở đây là sau khi chạy giả ban đầu, để cả hai được thực hiện sau khi siêu dữ liệu tệp đã được sao chép vào bộ đệm I / O.) cksumtrong cả hai trường hợp, chỉ để chứng minh rằng đầu ra độc lập với phương thức được sử dụng.
$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 basename -a | cksum'
2532163462 546663
real 0m0.063s
user 0m0.058s
sys 0m0.040s
$ time sh -c 'find /usr/lib -type f -print0 | xargs -0 -n 1 basename | cksum'
2532163462 546663
real 0m14.504s
user 0m12.474s
sys 0m3.109s
Như bạn có thể thấy, nó thực sự nhanh hơn đáng kể để tránh khởi chạy basenamemọi lúc.
basenamesẽ chấp nhận nhiều tên tệp mà không cần bất kỳ đối số dòng lệnh bổ sung nào. Việc sử dụng -aở đây là trên Linux. ( basename --versionnói với tôi basename (GNU coreutils) 8.28.)