GNU/Linux >> Znalost Linux >  >> Linux

Převod `pro File In` na `najít`, aby se skript mohl aplikovat rekurzivně?

Mám nápad spustit bash skript ke kontrole některých podmínek a použít ffmpeg převést všechna videa v mém adresáři z libovolného formátu do .mkv a funguje to skvěle!

Jde o to, že jsem nevěděl, že for file in smyčka nefunguje rekurzivně (https://stackoverflow.com/questions/4638874/how-to-loop-through-a-directory-recursively)

Ale sotva rozumím „potrubím“ a těším se, až uvidím příklad a vyjasním některé nejistoty.

Mám na mysli tento scénář, který by mi podle mě hodně pomohl pochopit.

Předpokládejme, že mám tento fragment bash skriptu:

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

Co to dělá, je, že pro aktuální adresář vyhledá jakýkoli *.mkv *avi *mp4 *flv *ogg *mov pak deklarujte, že výstup má příponu .mkv poté smažte původní soubor a výstup by měl být uložen do stejné složky, ve které je původní video.

  1. Jak to mohu převést, aby běželo rekurzivně? pokud použiji find , kde deklarovat proměnnou $file ? A kde byste měli deklarovat $target ? Jsou všechny find jen opravdu jednovrstvé? Opravdu potřebuji předat soubor do proměnné $file , protože stále budu muset spustit kontrolu stavu.

  2. A za předpokladu, že (1) je úspěšná, jak zajistit, aby byl splněn požadavek „výstup by pak měl být uložen do stejné složky, ve které je původní video“?

Přijatá odpověď:

Máte tento kód:

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

který běží v aktuálním adresáři. Chcete-li to změnit na rekurzivní proces, máte několik možností. Nejjednodušší (IMO) je použít find jak jsi navrhl. Syntaxe pro find je velmi „un-UNIX-like“, ale principem je, že každý argument lze použít s podmínkami AND nebo OR. Zde řekneme „Pokud se tento název souboru shoduje NEBO se shoduje tento název souboru, pak vytiskni “. Vzory názvů souborů jsou v uvozovkách, aby se k nim shell nemohl dostat (nezapomeňte, že shell je zodpovědný za rozšíření všech neuvedených vzorů, takže pokud jste měli vzor v uvozovkách *.mp4 a měli jste janeeyre.mp4 ve vašem aktuálním adresáři by shell nahradil *.mp4 se shodou a find uvidí -name janeeyre.mp4 místo vašeho požadovaného -name *.mp4; zhorší se to, pokud *.mp4 odpovídá více jménům…). Před závorkami je \ také proto, aby se je shell nepokoušel použít jako značky podslupky (můžeme místo toho citovat závorky, pokud dáváte přednost:'(' ).

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

Výstup tohoto musí být vložen do vstupu while smyčka, která postupně zpracovává každý soubor:

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

Nyní zbývá pouze spojit dvě části dohromady pomocí trubky | takže výstup find se stane vstupem while smyčka.

Související:Může CloudMagic prohledávat obsah souboru v Dropboxu?

Při testování tohoto kódu bych doporučil předponu oběma ffmpeg a rm s echo takže můžete vidět, co by být proveden – a jakými cestami.

Zde je konečný výsledek včetně echo výroky, které doporučuji k testování:

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. 8 strašidelných příkazů, které pronásledují terminál

  2. Proč skript Bash nerozpozná aliasy?

  3. Bash skript k odstranění nejstaršího souboru ze složky?

  1. Nedaří se vám získat správný výstupní kód ze skriptu?

  2. Jak na skript Shell vyhnout se Sigpipe, který by byl způsoben použitím uzavřeného deskriptoru souboru?

  3. Proměnná ve skriptu Bash, která si zachovává hodnotu z posledního spuštění

  1. Jak mohu rekurzivně kopírovat soubory podle přípony souboru a zachovat adresářovou strukturu?

  2. Jak rekurzivně zobrazit obsah souboru?

  3. Jak mohu najít nejstarší soubor ve stromu adresářů