Jawaban:
Di GNU find
Anda dapat menggunakan -printf
parameter untuk itu, misalnya:
find /dir1 -type f -printf "%f\n"
-o
memiliki prioritas lebih rendah daripada yang tersirat -a
, sehingga Anda akan sering ingin mengelompokkan -o
argumen Anda )
Jika temuan Anda tidak memiliki opsi -printf, Anda juga dapat menggunakan nama samaran:
find ./dir1 -type f -exec basename {} \;
... {} ';'
Gunakan -execdir
yang secara otomatis menyimpan file saat ini {}
, misalnya:
find . -type f -execdir echo '{}' ';'
Anda juga dapat menggunakan $PWD
sebagai gantinya .
(pada beberapa sistem itu tidak akan menghasilkan titik ekstra di depan).
Jika Anda masih mendapat titik tambahan, Anda juga dapat menjalankan:
find . -type f -execdir basename '{}' ';'
-execdir utility [argument ...] ;
The
-execdir
utama adalah identik dengan-exec
primer dengan pengecualian bahwa utilitas akan dieksekusi dari direktori yang memegang file saat ini .
Saat digunakan +
sebagai pengganti ;
, kemudian {}
diganti dengan sebanyak mungkin nama path untuk setiap pemanggilan utilitas. Dengan kata lain, itu akan mencetak semua nama file dalam satu baris.
./filename
bukan filename
. Tergantung pada kebutuhan Anda, mungkin atau mungkin tidak baik-baik saja.
$PWD
bukan .
.
Jika Anda menggunakan GNU find
find . -type f -printf "%f\n"
Atau Anda dapat menggunakan bahasa pemrograman seperti Ruby (1.9+)
$ ruby -e 'Dir["**/*"].each{|x| puts File.basename(x)}'
Jika Anda suka solusi bash (setidaknya 4)
shopt -s globstar
for file in **; do echo ${file##*/}; done
Jika Anda ingin menjalankan beberapa tindakan terhadap nama file saja, menggunakan basename
bisa jadi sulit.
Sebagai contoh ini:
find ~/clang+llvm-3.3/bin/ -type f -exec echo basename {} \;
hanya akan mengulang nama dasar /my/found/path
. Bukan yang kita inginkan jika kita ingin mengeksekusi pada nama file.
Tetapi Anda bisa kemudian xargs
output. misalnya untuk membunuh file dalam direktori berdasarkan nama di direktori lain:
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
dan -execdir
lambat, xargs
adalah raja.
$ 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
Paralelisme juga membantu.
Lucunya saya tidak bisa menjelaskan kasus terakhir xargs
tanpa -n1
. Ini memberikan hasil yang benar dan tercepat¯\_(ツ)_/¯
( basename
hanya membutuhkan 1 argumen jalan tetapi xargs
akan mengirim semuanya (sebenarnya 5000) tanpa -n1
. Tidak berfungsi di linux dan openbsd, hanya macOS ...)
Beberapa angka yang lebih besar dari sistem linux untuk melihat bagaimana -execdir
membantu, tetapi masih jauh lebih lambat daripada paralel 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
adalah -execdir
yang menjadi tercepat karena menciptakan proses baru adalah operasi yang relatif mahal.
Jujur basename
dan dirname
solusinya lebih mudah, tetapi Anda juga dapat memeriksanya:
find . -type f | grep -oP "[^/]*$"
atau
find . -type f | rev | cut -d '/' -f1 | rev
atau
find . -type f | sed "s/.*\///"
Seperti yang telah ditunjukkan orang lain, Anda dapat menggabungkan find
dan basename
, tetapi secara default basename
program hanya akan beroperasi pada satu jalur pada satu waktu, sehingga yang dapat dieksekusi harus diluncurkan satu kali untuk setiap jalur (menggunakan salah satu find ... -exec
atau find ... | xargs -n 1
), yang mungkin berpotensi lambat.
Jika Anda menggunakan -a
opsi aktif basename
, maka ia dapat menerima beberapa nama file dalam satu pemanggilan tunggal, yang berarti bahwa Anda kemudian dapat menggunakan xargs
tanpa -n 1
, untuk mengelompokkan jalur bersama menjadi jumlah pemanggilan yang jauh lebih kecil basename
, yang seharusnya lebih efisien.
Contoh:
find /dir1 -type f -print0 | xargs -0 basename -a
Di sini saya telah menyertakan -print0
dan -0
(yang harus digunakan bersama-sama), untuk mengatasi spasi putih di dalam nama file dan direktori.
Berikut ini adalah perbandingan waktu, antara versi xargs basename -a
dan xargs -n1 basename
. (Demi perbandingan suka-dengan-suka, timing yang dilaporkan di sini adalah setelah dummy run awal, sehingga keduanya dilakukan setelah file metadata telah disalin ke cache I / O.) Saya telah mengirim output ke cksum
dalam kedua kasus, hanya untuk menunjukkan bahwa output tidak tergantung pada metode yang digunakan.
$ 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
Seperti yang Anda lihat, ini sebenarnya jauh lebih cepat untuk menghindari peluncuran basename
setiap saat.
basename
akan menerima beberapa nama file tanpa memerlukan argumen baris perintah tambahan. Penggunaan di -a
sini adalah di Linux. ( basename --version
Memberitahu saya basename (GNU coreutils) 8.28
.)