2012-10-18 42 views
9

Tôi muốn đệ quy đổi tên tất cả các thư mục chứa chuỗi foo bằng cách thay thế một phần của chuỗi bằng Thanh. Tôi đã có một cái gì đó như thế này cho đến nay, nhưng nó không hoàn toàn làm việc. Tôi cũng muốn tìm kiếm foo để được tìm kiếm không phân biệt chữ hoa chữ thường.Đệ quy đổi tên thư mục trong bash

find . -type d -exec bash -c 'mv "$1" "${1//foo/Bar}"' -- {} \;

Có bất kỳ tao nhã một lớp lót có thể được tốt hơn so với nỗ lực này? Tôi đã thực sự thử một vài nhưng nghĩ rằng tôi muốn trì hoãn các chuyên gia. Lưu ý: Tôi đang thực hiện việc này trên hệ thống Mac OS X và không có các công cụ như đổi tên được cài đặt.

+0

Bạn có một lỗi? –

+0

Nếu nó là một bộ đếm thời gian, nó không cần phải là một lớp lót :) – user1154664

Trả lời

11

Hãy thử đoạn mã sau sử dụng tham số mở rộng

find . -type d -iname '*foo*' -depth -exec bash -c ' 
    echo mv "$1" "${1//[Ff][Oo][Oo]/BAr}" 
' -- {} \; 

Nhưng đặt cược tốt nhất của bạn sẽ là prename lệnh (đôi khi tên rename hoặc file-rename)

find . -type d -iname '*foo*' -depth -exec rename '[email protected]@[email protected]' {} + 

Và nếu bạn đang sử dụng bash4 hoặc zsh (** có nghĩa là đệ quy):

shopt -s globstar 
rename -n '[email protected]@[email protected]' **/*foo*/ 

Nếu nó phù hợp với nhu cầu của bạn, hãy xóa công tắc -n (chạy khô) để đổi tên cho thực.

MỘT SỐ DOC

rename ban đầu được viết bởi cha của Perl, Larry Wall mình.

+2

arcane, xấu xí và lộng lẫy –

+0

@sputnick - [Tôi sẽ vui vẻ upvote nếu bạn loại bỏ phiên bản 'sed'.] (http://mywiki.wooledge.org/ParsingLs) :-) – ghoti

+0

Đã thêm '-depth' để xử lý subdir đầu tiên –

5
find . -type d -iname '*foo*' -exec bash -O nocasematch -c \ 
    '[[ $1 =~ (foo) ]] && mv "$1" "${1//${BASH_REMATCH[1]}/Bar}"' -- {} \; 

Pro: Tránh được.
Con: Sẽ không tìm thấy tất cả các kết quả phù hợp nếu có nhiều trường hợp trong các trường hợp khác nhau.
Con: Thật lố bịch.

+0

OP cần một sự thay thế không phân biệt chữ hoa chữ thường. –

+0

Và '-name' sẽ không khớp với" * FOO * " –

+0

** + 1 ** - Đã chỉnh sửa, có vẻ như nó sẽ hoạt động. Và có, nó là một chút vô lý. :-) – ghoti

6

Tôi nghi ngờ vấn đề là làm cho nó hoạt động với mkdir -p foo/foo/foo.

Về vấn đề này, tôi nghĩ một giải pháp dựa trên find có thể sẽ không hoạt động do danh sách đường dẫn có thể được xác định trước.

Sau đây là không có cách nào nhã, và trải dài định nghĩa của một một liner, nhưng hoạt động cho kỳ thi trên.

$ mkdir -p foo/foo/foo 

$ (shopt -s nullglob && _() { for P in "$1"*/; do Q="${P//[Ff][Oo][Oo]/bar}"; mv -- "$P" "$Q"; _ "$Q"; done } && _ ./) 

$ find 
. 
./bar 
./bar/bar 
./bar/bar/bar 
+0

** + 1 ** - Điểm tuyệt vời. Arcane sử dụng bash. Công việc tốt đẹp. :) – ghoti

0

Tôi đã tìm kiếm câu trả lời tương tự và điều này đã làm việc:

find . -depth -name 'foo' -execdir bash -c 'mv "$0" ${0//foo/Bar}"' {} \; 
Các vấn đề liên quan