Di chuyển mọi tập tin không phải là một thư mục


14

Tôi có một thư mục mà tôi đang cố gắng dọn sạch có chứa cả tệp và thư mục con. Những gì tôi đang cố gắng làm rất đơn giản: di chuyển tất cả các tệp vào một thư mục khác, nhưng để lại tất cả các thư mục con như hiện tại.

Tôi đang nghĩ một cái gì đó như:

mv [*_but_no_dirs] ./other_directory

Có vẻ như nên có một cách đơn giản để làm điều này với các ký tự đại diện *và biểu thức chính quy ...

Bất cứ ai cũng có ý tưởng?


1
Vì vậy, di chuyển tất cả các tệp trong thư mục con, nhưng bỏ qua bất kỳ trong thư mục con?
Wilf

@Wilf: Chính xác.
hỏi

2
Trong zsh, bạn có thể làm mv **/*(.) ./other_directory- với bash, bạn cần phải sử dụng các lệnh bên ngoài như thế find.
trời ơi

Câu trả lời:


12

Regex không liên quan ở đây. Ký tự đại diện trong bash (giống như hầu hết các shell khác) chỉ khớp với các tệp dựa trên tên tệp, không dựa trên loại tệp hoặc các đặc điểm khác. Có một cách để khớp theo loại: thêm /vào cuối mẫu làm cho nó chỉ khớp các thư mục hoặc liên kết tượng trưng đến thư mục. Bằng cách này, bạn có thể di chuyển các thư mục, sau đó di chuyển những gì còn lại và di chuyển các thư mục trở lại - cồng kềnh nhưng nó hoạt động.

tmp=$(TMPDIR=.. mktemp -d)
mv -- */ "$tmp"
mv -- * "$tmp"/other_directory/
mv "$tmp"/* .
rmdir "$tmp"

Một cách tiêu chuẩn để khớp các tệp theo loại là gọi find.

find . -name . -o -type d -prune -o -exec sh -c 'mv "$@" "$0"' other_directory/ {} +

Trong zsh, bạn có thể sử dụng vòng loại toàn cầu để khớp các tệp theo loại. Vòng .loại phù hợp với các tập tin thông thường; sử dụng ^/để khớp với tất cả các thư mục không hoặc -^/cũng bao gồm các liên kết tượng trưng đến các thư mục.

mv -- *(.) other_directory/

Trong bất kỳ shell, bạn có thể chỉ cần lặp.

for x in *; do
   if ! [ -d "$x" ]; then
     mv -- "$x" other_directory/
   fi
done

8

Bạn có thể sử dụng một cái gì đó như

find . -maxdepth 1 \( ! -type d \) -exec sh -c 'mv  "$@" MYDIR' _ {} \;

Đầu tiên chúng ta sử dụng findđể chỉ nhìn trong directoy hiện tại, sau đó chúng ta bỏ qua các thư mục bằng cách sử dụng ! -type d cuối cùng chúng ta thực thi shvà di chuyển mọi thứ đến thư mục đích. Bạn có thể thử {} +ở cuối sẽ nhanh hơn.


2
Một chút giải thích, xin vui lòng ...
hỏi

1
@Questionmark Tôi đã cập nhật câu trả lời và đã thêm một số lời giải thích. Ngoài ra, cũng đáng để truy cập mywiki.wooledge.org/UsingFind
Valentin Bajrami

Tại sao bạn đề nghị -exec sh -c 'mv "$@" MYDIR' _ {} \;chứ không phải -exec mv {} MYDIR \;? Chỉ để có được một cái gì đó có thể được sắp xếp hợp lý bằng cách thay đổi \;thành một +? Bạn có thể làm điều đó với các -exec mv -t MYDIR {} +hình thức.
Scott

@Scott Tôi không có ý tưởng về -tcờ. Tôi cũng đã giải thích trong câu trả lời rằng +nhanh hơn nhưng không phải tất cả các findphiên bản đều hỗ trợ nó. Vì vậy, đoạn mã trên tương thích khá nhiều với bất kỳ findhoặc shell nào được sử dụng.
Valentin Bajrami

1
@ val0x00ff: mã hóa trên, mã trên tương thích với bất kỳ findhoặc vỏ nào được sử dụng. Đúng, nhưng cũng vậy find … -exec mv {} MYDIR \;, và sử dụng ít tài nguyên hơn … -exec sh -c 'mv "$@" MYDIR' _ {} \;.
Scott

0

Nó có khả năng hơi nguy hiểm nhưng

cp * destination/
rm *

Vì cả cp và rm sẽ không hoạt động trên các thư mục mà không có công tắc -r.


-1

Tôi sẽ đề nghị chỉ cần làm mv *.* destination/với đích / là thư mục bạn đang di chuyển đến.



2
Tên thư mục có thể chứa 'dấu chấm' và tên tệp có thể loại trừ nó (và thường làm) vì vậy *.*sẽ di chuyển một số thư mục và để lại một số tệp, đó không phải là điều người hỏi muốn.
dave_thndry_085

Xin lỗi nhưng điều này là hoàn toàn sai. Nó chỉ đơn giản là di chuyển bất cứ thứ gì có dấu chấm trong tên của nó và không di chuyển bất cứ thứ gì mà không có. Các dấu chấm không phải là độc quyền đối với các tệp và chúng cũng không được yêu cầu bởi các tệp, vì vậy điều này sẽ chỉ di chuyển một lựa chọn ngẫu nhiên các tệp và thư mục.
terdon

-2
mv $(ls -l | grep "^-" | awk '{print $9}') ./folder_where_move
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.