Câu trả lời:
Trong GNU find
bạn có thể sử dụng -printf
tham số cho điều đó, ví dụ:
find /dir1 -type f -printf "%f\n"
-o
có độ ư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 -execdir
tự động giữ tệp hiện tại {}
, ví dụ:
find . -type f -execdir echo '{}' ';'
Bạn cũng có thể sử dụng $PWD
thay 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
-execdir
là giống hệt với-exec
chí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.
./filename
thay 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.
$PWD
thay 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 basename
có 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 {} \;
-exec
và -execdir
là chậm, xargs
là 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
xargs
song song cũng giúp.
Đủ vui tôi không thể giải thích trường hợp cuối cùng xargs
mà không có -n1
. Nó cho kết quả chính xác và nhanh nhất¯\_(ツ)_/¯
( basename
chỉ mất 1 đối số đường dẫn nhưng xargs
sẽ 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 -execdir
giú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
find
nó -execdir
trở 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 find
và basename
, nhưng theo mặc định basename
chươ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 ... -exec
hoặc find ... | xargs -n 1
), có thể có khả năng bị chậm.
Nếu bạn sử dụng -a
tù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 xargs
mà 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 -print0
và -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 -a
và xargs -n1 basename
cá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.) cksum
trong 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 basename
mọi lúc.
basename
sẽ 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 --version
nói với tôi basename (GNU coreutils) 8.28
.)