thêm các ký tự đặc biệt vào tên thư mục


3

Tôi có một danh sách rất dài các thư mục với quy ước đặt tên sau

ABS1789_2563-01
ABS1789_2563-02
ABS1789_2563-02

.
.
.

Làm cách nào tôi có thể thêm "-" giữa ABS và 1789 sau đó thay thế "_" bằng "-" trong khoảng từ 1789 đến 2563 bằng cách sử dụng bash?

Câu trả lời:


4
IFS="\n"                        # Handle files with spaces in the names
for file in ABS*; do
    newfile="${file/ABS/ABS-}"  # Add the hyphen following ABS
    newfile="${newfile/_/-}"    # Change the underscore to a hyphen
    mv "$file" "$newfile"       # Make the change
done

Theo ý kiến ​​của Tony bên dưới, một phiên bản sử dụng tổng quát hơn có thể như sau:

IFS="\n"                          # Handle files with spaces in the names
for file in ABS*; do
    newfile="${file/foo/bar}"     # Replace foo with bar
    newfile="${newfile/baz/quux}" # Replace baz with quux (repeat as needed)
    if [[ "$file" == "$newfile" ]]; then
        echo "Not renaming $file - no change decreed."
    elif [[ -f "$newfile" ]]; then
        echo "Not renaming $file - $newfile already exists."
    else
        mv -- "$file" "$newfile"       # Make the change
    fi
done

1
Câu trả lời tốt. Cài đặt IFSlà không cần thiết, ngay cả khi các tệp của bạn có khoảng trắng (Tôi đã kiểm tra điều này trong Bash). Trong trường hợp chung (trong đó, không giống như ở đây, bạn không thể đảm bảo thay thế), có thể đáng để thử nghiệm [ "x$file" = "x$newfile" ] || mv -- "$file" "$newfile"để tránh mvphàn nàn về cũ và mới bằng nhau nếu không thay thế phù hợp (tôi cũng đã bảo vệ chống lại các tệp bắt đầu bằng -, chúng tôi cũng bảo vệ biết sẽ không xảy ra trong trường hợp cụ thể này).
Toby Speight

2

Một câu trả lời phù hợp phụ thuộc vào cách các tên có thể khác nhau. Bạn có thể chuyển đổi tên bằng cách sử dụng thay thế tham số tích hợp của shell nếu bạn giả sử độ rộng trường không đổi. Đó là tương đối hạn chế về phạm vi.

Thú vị hơn là sử dụng các lớp nhân vật trong sed:

newname=$(echo "$oldname" | sed -e 's/^\([[:alpha:]]\+\)\([[:digit:]]\+\)_/\1-\2-/')

nghĩa là, sau một tiền tố chữ cái hàng đầu, thêm dấu gạch ngang và sau đó sau các chữ số kết thúc bằng dấu gạch dưới, hãy thay đổi thành dấu gạch ngang.

Không giống như các giải pháp có thể sử dụng thay thế tham số, phương pháp này cho phép bất kỳ độ dài (khác không) từ tiền tố chữ số và chữ số. Vì vậy, bạn có thể có điều này như là đầu vào:

ABS1789_2563-01
ABS1789_2563-02
ABS1789_2563-02
ABSOLUTE1789_2563-01
ABSURD1789_2563-02
ABSOLVE1789_2563-02
PREFIX1793939389_2563-02

đặt nó trong một kịch bản

#!/bin/sh
for oldname in `cat foo4.txt`
do
newname=$(echo "$oldname" | sed -e 's/^\([[:alpha:]]\+\)\([[:digit:]]\+\)_/\1-\2-/')
echo "$oldname ->$newname"
done

đưa ra đầu ra này (trong một vòng lặp phù hợp):

ABS1789_2563-01 ->ABS-1789-2563-01
ABS1789_2563-02 ->ABS-1789-2563-02
ABS1789_2563-02 ->ABS-1789-2563-02
ABSOLUTE1789_2563-01 ->ABSOLUTE-1789-2563-01
ABSURD1789_2563-02 ->ABSURD-1789-2563-02
ABSOLVE1789_2563-02 ->ABSOLVE-1789-2563-02
PREFIX1793939389_2563-02 ->PREFIX-1793939389-2563-02

1

Nếu tất cả bắt đầu bằng ABS1789_2563-

for f in ABS*; do mv "$f" ABS-1789-2563-${f:13}; done

Đây

ABS-1789-2563-

chỉ đơn giản là mã hóa cứng theo giả định, tất cả các thư mục của bạn bắt đầu với ABS1789_2563- .

${f:13}

mở rộng đến cuối tham số $fbắt đầu từ offset 13 - thường được gọi là chuỗi con . Trong bash mở rộng chuỗi con .

Xem 3.5.3 Mở rộng tham số Shell , phần:

${parameter:offset}
${parameter:offset:length}

Vui lòng, ý nghĩa của số 13 ở cuối lệnh của bạn là gì. cảm ơn rất nhiều!

1
${var:13}ước tính "giá trị của biến varbắt đầu từ ký tự thứ mười ba". Vì vậy, nếu varđược đặt thành qwertyuiopasdfghjkl, ${var:13}sẽ tương đương với fghjkl.
DopeGhoti
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.