2013-05-14 36 views
41

Tôi đang có các tệp như a_dbg.txt, b_dbg.txt ... trong hệ thống Suse 10. Tôi muốn viết một kịch bản shell bash mà nên đổi tên các tập tin này bằng cách loại bỏ "_dbg" từ chúng.Tìm nhiều tệp đệ quy và đổi tên trong linux

Google đã đề xuất tôi sử dụng lệnh rename. Vì vậy, tôi đã thực hiện lệnh rename _dbg.txt .txt *dbg* trên CURRENT_FOLDER

Thực tế của tôi CURRENT_FOLDER chứa các tệp bên dưới.

CURRENT_FOLDER/a_dbg.txt 
CURRENT_FOLDER/b_dbg.txt 
CURRENT_FOLDER/XX/c_dbg.txt 
CURRENT_FOLDER/YY/d_dbg.txt 

Sau khi thực hiện lệnh rename,

CURRENT_FOLDER/a.txt 
CURRENT_FOLDER/b.txt 
CURRENT_FOLDER/XX/c_dbg.txt 
CURRENT_FOLDER/YY/d_dbg.txt 

nó không làm đệ quy, làm thế nào để làm cho lệnh này để đổi tên tập tin trong tất cả các thư mục con. Giống như XXYY Tôi sẽ có rất nhiều thư mục con có tên là không thể đoán trước. Và cũng CURRENT_FOLDER của tôi cũng sẽ có một số tệp khác.

+3

tôi nhận được 'bareword "..." không được phép trong khi "tàu ngầm nghiêm ngặt" được sử dụng tại (eval 1) dòng 1.' –

Trả lời

82

Bạn có thể sử dụng find để tìm tất cả các file phù hợp với đệ quy:

$ find . -iname "*dbg*" -exec rename _dbg.txt .txt '{}' \; 

EDIT:'{}'\; là?

Đối số -exec làm cho tìm thấy thực hiện rename cho mọi tệp phù hợp được tìm thấy. '{}' sẽ được thay thế bằng tên đường dẫn của tệp. Mã thông báo cuối cùng, \; chỉ có để đánh dấu sự kết thúc của biểu thức exec.

Tất cả những gì được mô tả độc đáo nằm trong man page để tìm:

-exec utility [argument ...] ; 
     True if the program named utility returns a zero value as its 
     exit status. Optional arguments may be passed to the utility. 
     The expression must be terminated by a semicolon (``;''). If you 
     invoke find from a shell you may need to quote the semicolon if 
     the shell would otherwise treat it as a control operator. If the 
     string ``{}'' appears anywhere in the utility name or the argu- 
     ments it is replaced by the pathname of the current file. 
     Utility will be executed from the directory from which find was 
     executed. Utility and arguments are not subject to the further 
     expansion of shell patterns and constructs. 
+0

@kamituel Cảm ơn. Tôi đang học linux và sử dụng tìm thấy vài lần tôi đã tự hỏi những gì có nghĩa là. cảm ơn lời giải thích tốt đẹp. Bạn có thể nói những gì -iname không? và chúng ta có thể sử dụng lệnh trên (trong Centos 7) như 'find. -type f "* dbg *" -exec đổi tên "_dbg.txt" ".txt" * {} \; ' –

+0

tôi đã kiểm tra nó và nó chỉ hoạt động trên các tệp không có trên thư mục. –

+0

Tôi gặp lỗi này nhiều lần: 'Chữ số bát phân bất hợp pháp '9' tại (mã do người dùng cung cấp), ở cuối dòng'. Tôi đã thử cả hai dấu ngoặc đơn, dấu ngoặc kép và không có dấu ngoặc kép cho các đối số của 'đổi tên'. Cụ thể là tôi đang cố thay thế '0123-MISC' bằng '0123_AB_MISC'. đây là lệnh của tôi 'tìm. -iname "* 0123-MISC *" - đổi tên đổi tên 0123-MISC 0123_AB_MISC {} \; ' – Eddy

10

với bash:

shopt -s globstar nullglob 
rename _dbg.txt .txt **/*dbg* 
+3

Giải pháp tuyệt vời. Tôi đã phải kích hoạt các tùy chọn bash với 'shopt -s globstar nullstar'. Đối với công cụ đổi tên được cài đặt thông qua 'brew install rename' trên MacOS, tôi phải thực hiện' rename -s oldStuff newStuff **/* ' –

9

script nhỏ tôi đã viết để thay thế tất cả các file với phần mở rộng .txt để cpp mở rộng dưới/tmp và các thư mục con đệ quy

#!/bin/bash 

for file in $(find /tmp -name '*.txt') 
do 
    mv $file $(echo "$file" | sed -r 's|.txt|.cpp|g') 
done 
+5

Phương thức bị hỏng! xin vui lòng không làm 'cho tập tin trong $ (tìm ...)'. Xem [Tại sao bạn không nên phân tích đầu ra của ls (1)] (http://mywiki.wooledge.org/ParsingLs). –

1

Scipt above có thể được viết bằng một dòng:

find /tmp -name "*.txt" -exec bash -c 'mv $0 $(echo "$0" | sed -r \"s|.txt|.cpp|g\")' '{}' \; 
+3

-bash: lỗi cú pháp gần mã thông báo không mong muốn ')' – Steven

+0

@steven thử sử dụng số này. -name "* .txt" -exec bash -c 'mv $ 0 $ (echo "$ 0" | sed-r "s/.txt/.cpp/g")' '{}' \; – xxbinxx

-3

giải pháp cổ điển:

for f in $(find . -name "*dbg*"); do mv $f $(echo $f | sed 's/_dbg//'); done 
+3

Điều này hoàn toàn bị hỏng. Làm ơn, đừng làm thế. –

+0

'~/tmp $ mkdir a && cd a/&& chạm 1_dbg.txt && cd ..' ' ~/tmp $ cho f trong $ (find. -name "* dbg *"); làm mv $ f $ (echo $ f | sed 's/_dbg //'); done' '~/tmp $ cd a/ ~/tmp/a $ l tổng số 8 drwxrwxr-x 2 repu1sion repu1sion 4096 Sep 17 21:17. drwxrwxr-x 3 repu1sion repu1sion 4096 Sep 17 21:17 .. -rw-rw-r-- 1 repu1sion repu1sion 0 Sep 17 21:17 1.txt' – pulse

+1

Có thể nó _seems_ để làm việc, nhưng nó phá vỡ với tên tập tin mà chứa dấu cách hoặc ký tự glob. Bạn nói đó là một giải pháp _classic_, nhưng nó có khả năng là giải pháp bạn đưa ra, nhưng nó cho thấy những sai lầm khủng khiếp (xin lỗi để khắc nghiệt, nhưng dòng của bạn có thể được bao gồm trong sách giáo khoa như một ví dụ về những gì không làm; số lỗi). –

0

Nếu bạn chỉ muốn đổi tên và không ngại sử dụng một công cụ bên ngoài, sau đó bạn có thể sử dụng rnm. Lệnh sẽ là:

#on current folder 
rnm -dp -1 -fo -ssf '_dbg' -rs '/_dbg//' * 

-dp -1 sẽ làm cho nó đệ quy cho tất cả các thư mục con.

-fo ngụ ý chế độ chỉ tệp.

-ssf '_dbg' tìm kiếm tệp có _dbg trong tên tệp.

-rs '/_dbg//' thay thế _dbg bằng chuỗi trống.

Bạn có thể chạy lệnh trên với đường dẫn của CURRENT_FOLDER quá:

rnm -dp -1 -fo -ssf '_dbg' -rs '/_dbg//' /path/to/the/directory 
8

Đối đổi tên đệ quy Tôi sử dụng các lệnh sau:

find -iname \*.* | rename -v "s/ /-/g" 
+0

Cũng hữu ích để khôi phục các tệp sao lưu. 'find -iname \ *. * | đổi tên -v -f "s/\. bak // g" ' – Paolo

0

Bạn có thể sử dụng dưới đây.

rename --no-act 's/\.html$/\.php/' *.html */*.html 
Các vấn đề liên quan