GNU/Linux >> Belajar Linux >  >> Linux

Mengonversi `untuk File In` Menjadi `find` Agar Script Dapat Diterapkan Secara Rekursif?

Saya memiliki ide untuk menjalankan skrip bash untuk memeriksa beberapa kondisi dan menggunakan ffmpeg untuk mengonversi semua video di direktori saya dari format apa pun ke .mkv dan itu bekerja dengan baik!

Masalahnya, saya tidak tahu bahwa for file in loop tidak bekerja secara rekursif (https://stackoverflow.com/questions/4638874/how-to-loop-through-a-directory-recursively)

Tapi saya hampir tidak mengerti "piping" dan saya menantikan untuk melihat contoh dan menyelesaikan beberapa ketidakpastian.

Saya memikirkan skenario ini yang menurut saya akan banyak membantu saya untuk memahami.

Misalkan saya memiliki cuplikan skrip bash ini:

for file in *.mkv *avi *mp4 *flv *ogg *mov; do
target="${file%.*}.mkv"
    ffmpeg -i "$file" "$target" && rm -rf "$file"
done

Apa yang dilakukannya adalah, untuk direktori saat ini, cari *.mkv *avi *mp4 *flv *ogg *mov apa saja kemudian mendeklarasikan output untuk memiliki ekstensi menjadi .mkv kemudian setelah itu hapus file aslinya, maka outputnya harus disimpan ke folder yang sama dengan video aslinya.

  1. Bagaimana saya bisa mengonversi ini agar berjalan secara rekursif? jika saya menggunakan find , di mana mendeklarasikan variabel $file ? Dan di mana Anda harus mendeklarasikan $target ? Apakah semua find hanya benar-benar satu kalimat? Saya benar-benar perlu meneruskan file ke variabel $file , karena saya masih perlu menjalankan pemeriksaan kondisi.

  2. Dan, dengan asumsi bahwa (1) berhasil, bagaimana memastikan bahwa persyaratan "maka output harus disimpan ke folder yang sama dengan video asli" terpenuhi?

Jawaban yang Diterima:

Anda mendapatkan kode ini:

for file in *.mkv *avi *mp4 *flv *ogg *mov; do
target="${file%.*}.mkv"
    ffmpeg -i "$file" "$target" && rm -rf "$file"
done

yang berjalan di direktori saat ini. Untuk mengubahnya menjadi proses rekursif Anda memiliki beberapa pilihan. Cara termudah (IMO) adalah menggunakan find seperti yang Anda sarankan. Sintaks untuk find sangat "tidak seperti UNIX" tetapi prinsipnya di sini adalah bahwa setiap argumen dapat diterapkan dengan kondisi AND atau OR. Di sini, kita akan mengatakan “Jika nama file ini cocok ATAU nama file itu cocok, maka cetaklah “. Pola nama file dikutip sehingga shell tidak dapat menangkapnya (ingat bahwa shell bertanggung jawab untuk memperluas semua pola yang tidak dikutip, jadi jika Anda memiliki pola *.mp4 yang tidak dikutip dan Anda memiliki janeeyre.mp4 di direktori Anda saat ini, shell akan menggantikan *.mp4 dengan kecocokan, dan find akan melihat -name janeeyre.mp4 alih-alih -name *.mp4 yang Anda inginkan; semakin parah jika *.mp4 cocok dengan beberapa nama…). Tanda kurung diawali dengan \ juga untuk menjaga agar Shell tidak mencoba menjalankannya sebagai penanda subkulit (sebagai gantinya, kita dapat mengutip tanda kurung, jika diinginkan:'(' ).

find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print

Keluaran ini perlu dimasukkan ke dalam masukan while loop yang memproses setiap file secara bergantian:

while IFS= read file    ## IFS= prevents "read" stripping whitespace
do
    target="${file%.*}.mkv"
    ffmpeg -i "$file" "$target" && rm -rf "$file"
done

Sekarang yang tersisa hanyalah menggabungkan kedua bagian tersebut dengan pipa | sehingga output dari find menjadi input dari while lingkaran.

Terkait:Bisakah CloudMagic mencari konten file di Dropbox?

Saat Anda menguji kode ini, saya sarankan Anda menambahkan awalan keduanya ffmpeg dan rm dengan echo sehingga Anda dapat melihat apa yang akan dieksekusi – dan dengan jalur apa.

Berikut adalah hasil akhirnya, termasuk echo pernyataan yang saya rekomendasikan untuk pengujian:

find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print |
    while IFS= read file    ## IFS= prevents "read" stripping whitespace
        do
            target="${file%.*}.mkv"
            echo ffmpeg -i "$file" "$target" && echo rm -rf "$file"
        done

Linux
  1. Cara Menemukan Paket Yang Menyediakan File Tertentu Di Linux

  2. Jika Saya Mengubah Izin Pada File Tar, Apakah Itu Berlaku Untuk File Di Dalamnya?

  3. Bagaimana saya tahu nama file skrip dalam skrip Bash?

  1. 8 perintah menyeramkan yang menghantui terminal

  2. Apakah ada variabel jalur instal Qt yang dapat saya gunakan di file .pro?

  3. Bisakah proses init menjadi skrip shell di Linux?

  1. Bisakah Skrip Bash Dihubungkan ke File?

  2. Mengapa Skrip Bash Tidak Mengenal Alias?

  3. Lihat File Di Bawah Direktori Skrip yang Sama Ditemukan Di $path?