bash ilk isimden dosya çıkar


2

Dosyaları bu şekilde taşımaya çalışıyorum:

...
DLG023-00-01-sprite.TextGrid.json
DLG023-00-01.prosody.json
DLG023-01-01-sprite.ogg
DLG023-00-02-sprite.TextGrid.json
DLG023-00-02.prosody.json
DLG023-01-02-sprite.ogg
...
DLG028-00-01-sprite.TextGrid.json
DLG028-00-01.prosody.json
DLG028-01-01-sprite.ogg
...

örneğin ilgili klasörlerine, örneğin: dosyayı dialogue023/başladığında DLG023; ile dialogue024/başladığında DLG024; ve bunun gibi.

Tüm dosyalar ve dizinler aynı seviyededir.

Başka bir deyişle, bunun gibi komutlar üretmeye çalışıyorum:

mv DLG023-00-01-sprite.ogg dialogue023/

İlk numarayı dosya adından nasıl çıkarabilirim?

Şimdiye kadar bu var:

for i in DLG*-*-*-sprite.ogg; do echo "${i//[^0-9]}";done

Ancak bu yalnızca birincisini istediğimde (örneğin: 23) tüm rakamları (örneğin: 230001) çıkarır.


1
Aslında değil ayıklamak numaralarını, bu nedenle soruya bir cevap değil, ama gibi prensipte aynı zamanda bir şeyler yapabiliriz for num in $(seq -f '%03g' 1 999); do test -d dialogue${num}||mkdir dialogue${num}; mv -t dialogue${num} DLG${num}-*; doneardından rmdir dialogue*- -f '%03g'999 uyan beri tüm sayılar en az üç basamak sıfır getirilmiş olan araçlar ve üç hane, tüm sayılar dizin isimlerinde üç hane olacak. rmdirDizin boş değilse düz başarısız olur, yani güvenlidir. Var mvolmayan dosyalardan gelen önemli olmayan hata çıktısını alın .
bir CVn

Her zaman 4-6 karakter mi?
Paul

Teşekkürler Michael, bu konuda gitmenin en akıllıca yolu.
Fabien Snauwaert

Her zaman 3-6 karakterleri (veya şimdilik 4-6).
Fabien Snauwaert

Yanıtlar:


1

-tSeçeneği olmayan OS X kullandığınızı varsayıyorum mv. Komut dosyası binlerce dosyayı işliyorsa, bu çok yavaş olacaktır.

    for file in DLG*; do
    # Extract the three digits after DLG
    getnum=${file%%-*}
    getnum=${getnum#???}

    # make the directory dialogue### or exit if there is an error
    echo mkdir -p "dialogue${getnum}" || exit

    echo mv "$file" "dialogue${getnum}"
    done

echoÖncesi mkdirve mvçıkış doğru ise, çıkarın .


ÇALIŞIYOR bir cazibe gibi. Bir göz açıp kapayıncaya kadar olmaz, ancak 19 klasör için saniyeler içinde gerçekleşir. Sırf meraktan: Üç basamağı tek bir adımda çıkarmanın bir yolu var mı?
Fabien Snauwaert

@Fabien Snauwaert- Subring genişletme yerine subring genişletmeyi tek adımda kullanabilirsiniz, ancak subring genişletme her kabukta mevcut değildir.
fd0

0

Bunu kullanarak mv komutunu oluşturabilirsiniz:

for f in DLG*; do echo "$f" | sed 's/DLG\([0-9]\+\).*/mv "\0" "dialogue\1\/"/g'; done

Şimdi, komut şöyle yazdırılır:

mv "DLG023-00-01.prosody.json" "dialogue023/"
[...]
mv "DLG028-00-01.prosody.json" "dialogue028/"
[...]

Eğer istediğin buysa, sadece çıkış yapan boru bashile çalıştırılacak:

for f in DLG*; do echo "$f" | sed 's/DLG\([0-9]\+\).*/mv "\0" "dialogue\1\/"/g'; done | bash

0

Bir satır çözümü kullanarak find:

find . -name DLG* -exec bash -c 'DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/"); mkdir "$DEST"; mv "$0" "$DEST"' {} \;
  • findkomut DLG*bu dizindeki dosyaları arayın .
  • Her sonuç için bash -ccümleyi yürütün .

In bashcümle:

  • DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/");find ( $0) 'daki her sonucu alır sedve ilk -(DLG ([0-9] +) -. *)' den önceki tüm sayıları kullanarak dialoguebu sayıları ( dialogue\1) takip eder ve çağrılan bir değişkene koyar DEST.
  • mkdir "$DEST" İstenilen klasörü yaratır.
  • mv "$0" "$DEST"' dosyayı bu dizine taşır.

1
Bu soruyu cevaplayabilse de, neden böyle olduğunu açıklayabilirseniz daha iyi bir cevap olabilir .
DavidPostill

0

Birkaç fikir:

for i in DLG*-\*-\*-sprite.ogg; do echo "${i//[^0-9]}" | head -c 2; echo ;done

Bunların hepsinin aynı olduğundan eminseniz:

for i in DLG*-\*-\*-sprite.ogg; do echo "${i:3:3}" ;done
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.