Saya memiliki server yang menerima file per klien setiap hari ke dalam direktori. Nama file dibuat sebagai berikut:
uuid_datestring_other-data
Sebagai contoh:
d6f60016-0011-49c4-8fca-e2b3496ad5a7_20160204_023-ERROR
uuid
adalah format standar uuid.datestring
adalah keluaran daridate +%Y%m%d
.other-data
panjang variabel tetapi tidak akan pernah berisi garis bawah.
Saya memiliki file format:
#
d6f60016-0011-49c4-8fca-e2b3496ad5a7 client1
d5873483-5b98-4895-ab09-9891d80a13da client2
be0ed6a6-e73a-4f33-b755-47226ff22401 another_client
...
Saya perlu memeriksa bahwa setiap uuid yang tercantum dalam file memiliki file yang sesuai di direktori, menggunakan bash.
Saya sudah sejauh ini, tetapi merasa seperti saya datang dari arah yang salah dengan menggunakan pernyataan if, dan saya perlu mengulang-ulang file di direktori sumber.
Variabel source_directory dan uuid_list telah ditetapkan sebelumnya dalam skrip:
# Check the entries in the file list
while read -r uuid name; do
# Ignore comment lines
[[ $uuid = \#* ]] && continue
if [[ -f "${source_directory}/${uuid}*" ]]
then
echo "File for ${name} has arrived"
else
echo "PANIC! - No File for ${name}"
fi
done < "${uuid_list}"
Bagaimana saya harus memeriksa bahwa file dalam daftar saya ada di direktori? Saya ingin menggunakan fungsionalitas bash sejauh mungkin, tetapi saya tidak menentang penggunaan perintah jika perlu.
command-line
bash
scripts
Arronikal
sumber
sumber
Jawaban:
Berjalan di atas file, buat array asosiatif di atas uuids yang terkandung dalam namanya (saya menggunakan ekspansi parameter untuk mengekstrak uuid). The, baca daftar, periksa array asosiatif untuk setiap uuid dan laporkan apakah file itu direkam atau tidak.
sumber
cd
masuk ke direktori dalam skrip, tetapi hanya ingin tahu demi mendapatkan pengetahuan.file=${file##*/}
.Berikut ini pendekatan yang lebih "bashy" dan ringkas:
Perhatikan bahwa sementara di atas cukup dan akan berfungsi dengan baik untuk beberapa file, kecepatannya tergantung pada jumlah UUID dan akan sangat lambat jika Anda perlu memproses banyak. Jika demikian, gunakan solusi @ choroba atau, untuk sesuatu yang sangat cepat, hindari shell dan hubungi
perl
:Hanya untuk menggambarkan perbedaan waktu, saya menguji pendekatan bash saya, choroba dan perl saya pada file dengan 20000 UUID yang 18001 memiliki nama file yang sesuai. Perhatikan bahwa setiap pengujian dijalankan dengan mengarahkan output skrip ke
/dev/null
.Bash saya (~ 3,5 mnt)
Choroba's (bash, ~ 0,7 dtk)
Perl saya (~ 0,1 dtk):
sumber
cd
masuk ke direktori dalam skrip, tetapi apakah ada metode di mana jalur file dapat dimasukkan dalam pencarian?${source_directory}
seperti yang Anda lakukan di skrip."$2"
dan berikan ke skrip sebagai argumen kedua.Ini murni Bash (yaitu tidak ada perintah eksternal), dan ini adalah pendekatan yang paling tepat yang dapat saya pikirkan.
Tetapi kinerja-bijaksana benar-benar tidak jauh lebih baik daripada apa yang Anda miliki saat ini.
Ini akan membaca setiap baris dari
path/to/file
; untuk setiap baris, maka akan menyimpan field pertama di$uuid
dan mencetak pesan jika file yang cocok polapath/to/directory/$uuid*
ini tidak ditemukan:Sebut saja dengan
path/to/script path/to/file path/to/directory
.Output sampel menggunakan file input sampel dalam pertanyaan pada hierarki direktori tes yang berisi file sampel dalam pertanyaan:
sumber
Idenya di sini adalah tidak perlu khawatir tentang kesalahan pelaporan shell akan melaporkan untuk Anda. Jika Anda mencoba
<
membuka file yang tidak ada, shell Anda akan mengeluh. Bahkan, itu akan menambahkan skrip Anda$0
dan nomor baris di mana kesalahan terjadi ke output kesalahan ketika itu ... Ini adalah informasi yang baik yang sudah disediakan secara default - jadi jangan repot-repot.Anda juga tidak perlu mengambil file dalam baris demi baris seperti itu - itu bisa sangat lambat. Ini memperluas seluruh hal dalam satu tembakan ke array argumen dibatasi ruang-putih dan menangani dua sekaligus. Jika data Anda konsisten dengan contoh Anda, maka
$1
akan selalu menjadi uuid Anda dan$2
akan menjadi milik Anda$name
. Jikabash
dapat membuka kecocokan dengan uuid Anda - dan hanya ada satu kecocokan seperti itu - makaprintf
terjadilah. Kalau tidak, shell tidak akan menulis diagnosa kepada stderr tentang alasannya.sumber
unset IFS
memastikan bahwa$(cat <uuid_file)
dibagi pada ruang putih. Kerang pecah secara$IFS
berbeda ketika hanya terdiri dari ruang putih atau tidak disetel. Ekspansi split seperti itu tidak pernah memiliki bidang nol karena semua urutan ruang putih hanya berdiri sebagai pembatas bidang tunggal. Selama hanya ada dua bidang non-white-space yang terpisah pada setiap baris itu harus bekerja, saya pikir. dibash
, anyway.set -f
memastikan bahwa ekspansi tanda kutip tidak diartikan untuk gumpalan, dan set + f memastikan bahwa gumpalan kemudian.<>
karena itu membuat file tidak ada.<
akan melaporkan seperti yang saya maksudkan. masalah yang mungkin dengan itu - dan alasan saya salah digunakan<>
di tempat pertama - adalah bahwa jika itu adalah file pipa tanpa pembaca atau seperti dev baris-buffered itu akan hang. yang bisa dihindari dengan menangani output kesalahan lebih eksplisit dan melakukan[ -f "$dir/$1"* ]
. kita berbicara tentang uuids di sini, dan karena itu seharusnya tidak pernah berkembang menjadi lebih dari satu file. itu agak bagus meskipun bagaimana melaporkan nama file yang gagal ke stderr seperti itu.<>
masih dapat digunakan dengan cara itu ...<>
lebih baik jika gumpal dapat memperluas ke direktori karena pada linux baca / tulis akan gagal dan katakan - itu direktori.bash
hanya akan menerima gir pengalihan jika hanya cocok dengan satu file. lihat diman bash
bawah REDIRECTION.Cara saya mendekatinya adalah dengan mendapatkan uuids dari file terlebih dahulu, lalu gunakan
find
Untuk keterbacaan,
Contoh dengan daftar file dalam
/etc/
, mencari passwd, grup, fstab, dan THISDOESNTEXIST nama file.Karena Anda telah menyebutkan direktori itu datar, Anda bisa menggunakan
-printf "%f\n"
opsi untuk hanya mencetak nama file itu sendiriApa yang tidak dilakukan adalah mendaftar file yang hilang.
find
Kerugian kecilnya adalah ia tidak memberi tahu Anda jika tidak menemukan file, hanya ketika itu cocok dengan sesuatu. Apa yang bisa dilakukan seseorang adalah mengecek output - jika output kosong, maka kita memiliki file yang hilangLebih mudah dibaca:
Dan inilah cara kerjanya sebagai skrip kecil:
Satu dapat digunakan
stat
sebagai alternatif, karena itu adalah direktori datar, tetapi kode di bawah ini tidak akan bekerja secara rekursif untuk subdirektori jika Anda memutuskan untuk menambahkannya:Jika kita mengambil
stat
ide dan menjalankannya, kita bisa menggunakan kode keluar stat sebagai indikasi apakah ada file atau tidak. Secara efektif, kami ingin melakukan ini:Contoh dijalankan:
sumber