Thử:
find . -mindepth 2 -type f -name '*.pdf' -exec bash -c 'f=${1#./}; mv "$1" "./${f//\//_}"' None {} \;
Điều này an toàn cho tất cả các tên tệp, ngay cả những tên có dòng mới trong tên của chúng.
Làm thế nào nó hoạt động
-mindepth 2
Điều này cho biết tìm thấy không xử lý bất kỳ tập tin đã có trong thư mục hiện tại.
-type f -name '*.pdf'
Điều này hạn chế tìm kiếm các tệp thông thường với pdf
sự mở rộng.
-exec bash -c '...' None {} \;
Điều này chạy lệnh trong chuỗi trích dẫn cung cấp tên tệp làm đối số đầu tiên, $1
.
Đối với mục đích của chúng tôi, chuỗi None
chỉ đơn giản là một giữ chỗ. Nó được gán cho $0
, theo các quy ước bash, là tên của lệnh mà chúng ta đang chạy.
f=${1#./}; mv "$1" "./${f//\//_}"
Điều này (a) loại bỏ tiền tố ./
từ tên tệp và (b) di chuyển tệp đến vị trí mong muốn với tên mới.
${1#./}
là một ví dụ về bash's loại bỏ tiền tố . Nó trả về chuỗi $1
với ./
loại bỏ từ đầu. ${f//\//_}
là một ví dụ về bash's thay thế mẫu . Nó trả về chuỗi $f
với tất cả /
thay thế bằng _
. Để đọc thêm về các tính năng này, xem phần trong man bash
được phép Mở rộng tham số .
Phiên bản hiệu quả hơn
Phiên bản trên gọi bash cho mọi tệp được tìm thấy. Ngoài ra, chúng ta có thể gọi bash chỉ một lần cho một số tệp được tìm thấy. Để làm điều này, chúng tôi gói lệnh của chúng tôi trong một for
vòng lặp:
find . -mindepth 2 -type f -name '*.pdf' -exec bash -c 'for f in "$@"; do f=${f#./}; echo mv "$f" "./${f//\//_}"; done' None {} +
Vấn đề thay thế
Giả sử rằng tất cả các tệp chúng ta muốn nằm trong một thư mục cấp hai và chúng ta muốn các tệp được di chuyển có thứ tự các tên thư mục được đảo ngược để thay vì ./path1_pathA_fileI.pdf
, chúng tôi kết thúc với ./pathA_path1_fileI.pdf
. Trong trường hợp này:
for d1 in */; do d1=${d1%/}; for d2 in "$d1"/*/; do d2=${d2%/}; p="${d2#$d1/}_$d1"; for f in "./$d2"/*.pdf; do echo mv "$f" "./${p}_${f#./$d2/}"; done; done; done
Hoặc, đối với những người thích các lệnh của họ trải rộng trên nhiều dòng:
for d1 in */
do
d1=${d1%/}
for d2 in "$d1"/*/
do
d2=${d2%/}
p="${d2#$d1/}_$d1"
for f in "./$d2"/*.pdf
do
echo mv "$f" "./${p}_${f#./$d2/}"
done
done
done