bash trích xuất số đầu tiên từ tên tệp


2

Tôi đang cố gắng di chuyển các tệp như thế này:

...
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
...

vào các thư mục tương ứng của chúng, ví dụ: di chuyển tệp đến dialogue023/khi bắt đầu bằng DLG023; đến dialogue024/khi nó bắt đầu với DLG024; vân vân

Tất cả các tập tin và thư mục ở cùng một cấp độ.

Nói cách khác, tôi đang cố gắng tạo ra các lệnh như thế này:

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

Làm thế nào tôi có thể trích xuất số đầu tiên từ tên tệp?

Cho đến nay tôi đã có điều này:

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

Nhưng điều này xuất ra tất cả các chữ số (ví dụ: 230001) khi tôi chỉ muốn cái đầu tiên (ví dụ: 23).


1
Nó không thực sự trích xuất các con số, vì vậy nó không phải là một câu trả lời cho câu hỏi, nhưng về nguyên tắc, bạn cũng có thể làm điều gì đó giống như for num in $(seq -f '%03g' 1 999); do test -d dialogue${num}||mkdir dialogue${num}; mv -t dialogue${num} DLG${num}-*; donesau rmdir dialogue*- -f '%03g'có nghĩa là tất cả các số được đệm bằng 0 đến ít nhất ba chữ số và vì 999 phù hợp với ba chữ số tất cả các số sẽ trở thành ba chữ số dài trong tên thư mục. Đồng bằng rmdirkhông thành công nếu thư mục không trống, vì vậy an toàn. Cú đúp cho đầu ra lỗi không quan trọng từ mvkhoảng các tệp không tồn tại.
CVn

Có phải nó luôn luôn chars 4-6?
Paul

Cảm ơn Michael, đó là cách thông minh để nói về nó.
Fabien Snauwaert

Nó luôn luôn là 3-6 (hoặc 4 - 6 giờ.)
Fabien Snauwaert

Câu trả lời:


1

Tôi giả sử rằng bạn đang sử dụng OS X, không có -ttùy chọn này mv. Điều này sẽ rất chậm nếu tập lệnh đang xử lý hàng ngàn tệp.

    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

Loại bỏ echotrước mkdirmvnếu đầu ra là satifactory.


Hoạt động như một lá bùa. Nó không xảy ra trong chớp mắt nhưng xảy ra trong vài giây cho 19 thư mục. Vì tò mò quá mức: có cách nào để trích xuất ba chữ số chỉ trong một bước không?
Fabien Snauwaert

@Fabien Snauwaert- Bạn có thể sử dụng mở rộng chuỗi con trong một bước thay vì loại bỏ chuỗi con nhưng mở rộng chuỗi con không có sẵn trong mọi shell.
fd0

0

Bạn có thể tạo lệnh mv bằng cách này:

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

Bây giờ, lệnh được in như thế này:

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

Nếu đó là những gì bạn muốn, chỉ cần đặt đường ống đầu ra bashđó và nó sẽ được thực thi:

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

0

Giải pháp một dòng sử dụng find:

find . -name DLG* -exec bash -c 'DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/"); mkdir "$DEST"; mv "$0" "$DEST"' {} \;
  • findlệnh tìm kiếm DLG*các tập tin từ thư mục này.
  • Đối với mỗi kết quả thực hiện bash -ccâu.

Trong bashcâu:

  • DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/");chọn mọi kết quả từ find ( $0) và sử dụng sedthay thế tất cả các số trước số đầu tiên -(DLG ([0-9] +) -. *) bằng cách dialoguetheo sau với các số đó ( dialogue\1) và đặt vào một biến được gọi DEST.
  • mkdir "$DEST" tạo thư mục cần thiết.
  • mv "$0" "$DEST"' di chuyển tập tin vào thư mục đó

1
Trong khi điều này có thể trả lời câu hỏi, nó sẽ là một câu trả lời tốt hơn nếu bạn có thể cung cấp một số lời giải thích tại sao nó làm như vậy.
DavidPostill

0

Một vài ý tưởng:

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

Nếu bạn chắc chắn rằng tất cả chúng đều có cùng chiều dài:

for i in DLG*-\*-\*-sprite.ogg; do echo "${i:3:3}" ;done
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.