it-swarm-vi.com

Làm thế nào để bạn di chuyển tất cả các tập tin (bao gồm cả ẩn) từ thư mục này sang thư mục khác?

Làm cách nào để di chuyển tất cả các tệp trong một thư mục (bao gồm cả các tệp bị ẩn) sang thư mục khác?

Ví dụ: nếu tôi có một thư mục "Foo" với các tệp ".hidden" và "notHidden" bên trong, làm cách nào để di chuyển cả hai tệp vào thư mục có tên "Bar"? Các mục sau không hoạt động, vì tệp ".hidden" nằm trong "Foo".

mv Foo/* Bar/

Hãy thử nó.

mkdir Foo
mkdir Bar
touch Foo/.hidden
touch Foo/notHidden
mv Foo/* Bar/
155
Cory Klein

Zsh

mv Foo/*(DN) Bar/

hoặc là

setopt -s glob_dots
mv Foo/*(N) Bar/

(Bỏ (N) Nếu bạn biết thư mục không trống.)

Bash

shopt -s dotglob nullglob
mv Foo/* Bar/

Ksh93

Nếu bạn biết thư mục không trống:

FIGNORE='.?(.)'
mv Foo/* Bar/

Tiêu chuẩn (POSIX) sh

for x in Foo/* Foo/.[!.]* Foo/..?*; do
  if [ -e "$x" ]; then mv -- "$x" Bar/; fi
done

Nếu bạn sẵn sàng để lệnh mv trả về trạng thái lỗi mặc dù đã thành công, thì đơn giản hơn nhiều:

mv Foo/* Foo/.[!.]* Foo/..?* Bar/

GNU tìm và GNU mv

find Foo/ -mindepth 1 -maxdepth 1 -exec mv -t Bar/ -- {} +

Tìm tiêu chuẩn

Nếu bạn không thay đổi thư mục nguồn:

cd Foo/ &&
find . -name . -o -exec sh -c 'mv -- "[email protected]" "$0"' ../Bar/ {} + -type d -Prune

Dưới đây là chi tiết hơn về việc kiểm soát xem các tệp chấm có khớp trong bash, ksh93 và zsh hay không.

Bash

Đặt tùy chọn dotglob .

$ echo *
none zero
$ shopt -s dotglob
$ echo *
..two .one none zero

Ngoài ra còn có linh hoạt hơn GLOBIGNORE biến , mà bạn có thể đặt thành danh sách các mẫu ký tự đại diện được phân tách bằng dấu hai chấm để bỏ qua. Nếu không được đặt (cài đặt mặc định), Shell hoạt động như thể giá trị trống nếu dotglob được đặt và như thể giá trị là .* Nếu tùy chọn không được đặt. Xem Mở rộng tên tệp trong hướng dẫn. Các thư mục phổ biến ... Luôn bị bỏ qua, trừ khi . Được khớp rõ ràng theo mẫu.

$ GLOBIGNORE='n*'
$ echo *
..two .one zero
$ echo .*
..two .one
$ unset GLOBIGNORE
$ echo .*
. .. ..two .one
$ GLOBIGNORE=.:..
$ echo .*
..two .one

Ksh93

Đặt biến FIGNORE . Nếu không được đặt (cài đặt mặc định), Shell hoạt động như thể giá trị là .*. Để bỏ qua ..., Chúng phải được khớp một cách rõ ràng (hướng dẫn trong ksh 93s + 2008-01-31 nói rằng ... Luôn bị bỏ qua , nhưng điều này không mô tả chính xác hành vi thực tế).

$ echo *
none zero
$ FIGNORE='@(.|..)'
$ echo *
..two .one none zero
$ FIGNORE='n*'
$ echo *
. .. ..two .one zero

Bạn có thể bao gồm các tệp chấm trong một mẫ bằng cách khớp chúng rõ ràng.

$ unset FIGNORE
$ echo @(*|.[^.]*|..?*)
..two .one none zero

Để mở rộng hết trống nếu thư mục trống, hãy sử dụng tùy chọn khớp mẫu N: ~(N)@(*|.[^.]*|..?*) hoặc ~(N:*|.[^.]*|..?*).

Zsh

Đặt tùy chọn dot_glob .

% echo *
none zero
% setopt dot_glob
% echo *
..two .one none zero

... Không bao giờ được khớp, ngay cả khi mẫu đó khớp với . Hàng đầu một cách rõ ràng.

% echo .*
..two .one

Bạn có thể bao gồm các tệp chấm trong một mẫu cụ thể với Dvòng loại toàn cầ .

% echo *(D)
..two .one none zero

Thêm N vòng loại toàn cầu để làm cho việc mở rộng trở nên trống rỗng trong một thư mục trống: *(DN).


Lưu ý: bạn có thể nhận được kết quả mở rộng tên tệp theo các đơn hàng khác nhau (ví dụ: none theo sau là .one Theo sau là ..two) Dựa trên cài đặt của bạn về LC_COLLATE, Các biến LC_ALLLANG.

178
#!/bin/bash

shopt -s dotglob
mv Foo/* Bar/

Từ man bash

dotglob Nếu được đặt, bash bao gồm tên tệp bắt đầu bằng '.' trong kết quả mở rộng tên đường dẫn.

24
SiegeX

Một cách đơn giản để làm điều này trong bash

mv {Foo/*,Foo/.*} Bar/

Nhưng điều này cũng sẽ di chuyển các thư mục.

Nếu bạn muốn di chuyển tất cả các tệp bao gồm ẩn nhưng không muốn di chuyển bất kỳ thư mục nào, bạn có thể sử dụng vòng lặp for và kiểm tra.

for i in $(ls -d {Foo/*,Foo/.*});do test -f $i && mv -v $i Bar/; done;

11
Boris Month

Một cách là sử dụng find:

find Foo/ -type f -exec mv -t Bar/ {} \+

Các -type f hạn chế lệnh find để tìm tập tin. Bạn nên điều tra -type, -maxdepth-mindepth tùy chọn của find để tùy chỉnh lệnh của bạn để giải thích cho các thư mục con. Tìm có một thời gian dài nhưng rất hữu ích trang thủ công .

4
Steven D

Hãy thử lệnh sao chép cp:

$ cp -r myfolder/* destinationfolder

cp -r có nghĩa là sao chép đệ quy, vì vậy tất cả các thư mục và tệp sẽ được sao chép.

Bạn có thể sử dụng lệnh remove rm để xóa thư mục:

$ rm -r myfolder

Xem thêm: di chuyển tất cả các tệp từ thư mục sang thư mục khác .

2
ucefkh

Đối với tối thiểu các bản phân phối Linux, sau đây nên hoạt động. Đầu tiên, thực hiện di chuyển cơ bản tất cả (mà bỏ lỡ các tệp ẩn). Sau đó, di chuyển tất cả các tệp ẩn (bao gồm cả ... sẽ không thực sự được di chuyển).

mv /sourceDir/* /destinationDir 2> /dev/null
mv /sourceDir/.* /destinationDir 2> /dev/null

Ghi chú : Nếu không có nội dung hiển thị, lệnh đầu tiên sẽ tạo thông báo lỗi. Lệnh thứ hai sẽ luôn luôn tạo ra lỗi cho biết nó không thể di chuyển .... Như vậy, chỉ cần đưa các lỗi vào /dev/null (như hình).

Nếu bạn cần cái này như một lớp lót, chỉ cần kết hợp chúng với dấu chấm phẩy:

mv /sourceDir/* /destinationDir 2> /dev/null; mv /sourceDir/.* /destinationDir 2> /dev/null
1
BuvinJ

Rsync là một tùy chọn khác:

rsync -axvP --remove-source-files sourcedirectory/ targetdirectory

Điều này hoạt động vì trong rsync dấu gạch chéo có vấn đề, sourcedirectory/ đề cập đến nội dung của thư mục, trong khi sourcedirectory sẽ đề cập đến chính thư mục đó.

Nhược điểm của phương pháp này là rsync sẽ chỉ dọn sạch các tệp sau khi di chuyển chứ không phải thư mục. Vì vậy, bạn còn lại với một cây sourcedirectory trống. Đối với cách giải quyết cho điều đó, xem:

Di chuyển tệp và xóa thư mục bằng rsync?

Vì vậy, trong khi điều này có thể không tối ưu cho các hoạt động di chuyển, nó có thể cực kỳ hữu ích cho các hoạt động sao chép.

1
Grumbel

Trả lời cho bash/cá

Đây là một cách để làm điều đó bằng cách sử dụng ký tự đại diện:

.[!.]* ..?* sẽ khớp tất cả các tệp bị ẩn ngoại trừ ...

.[!.]* ..?* * sẽ khớp tất cả các tệp (ẩn hoặc không) ngoại trừ ...

Và để trả lời ví dụ cụ thể của câu hỏi này, bạn cần cd foo && mv .[!.]* ..?* * ../bar

Giải thích

.[!.]* khớp với tên tệp bắt đầu bằng một dấu chấm, theo sau là bất kỳ ký tự nào ngoại trừ dấu chấm tùy ý theo sau bởi bất kỳ chuỗi nào. Điều này đủ gần nhưng nó bỏ lỡ các tệp bắt đầu bằng hai dấu chấm như ..foo. Để bao gồm các tệp như vậy, chúng tôi thêm ..?* khớp với tên tệp bắt đầu bằng hai dấu chấm, theo sau là bất kỳ ký tự nào, tùy ý theo sau bởi bất kỳ chuỗi nào.

Kiểm tra

Bạn có thể kiểm tra các ký tự đại diện này bằng các lệnh bên dưới. Tôi đã thử chúng thành công dưới bash và cá. Họ thất bại dưới sh, zsh, xonsh.

mkdir temp
cd temp
touch  a  .b  .bc  ..c  ..cd  ...d  ...de
ls .[!.]* ..?*
# you get this output:
          .b  .bc  ..c  ..cd  ...d  ...de
# cleanup
cd ..
rm -rf temp
1
ndemou

Tôi thấy rằng điều này hoạt động tốt cho bash và không cần thay đổi tùy chọn Shell

mv sourcedir/{*,.[^.]*} destdir/

BIÊN TẬP:

Vì vậy, như G-man đã nói, câu trả lời ban đầu của tôi không tuân thủ theo kiểu posix và khá giống với câu trả lời ndemou kèm ở trên với một thay đổi, đó là sử dụng mở rộng dấu ngoặc để tạo danh sách các chuỗi được thực hiện. Điều này chỉ có nghĩa là bạn không cần phải cd vào thư mục nguồn. Không phải là một sự thay đổi lớn thực sự, nhưng nó là khác nhau.

ví dụ: giả sử bạn đã có bố cục sau đây.

 $ tree -a
.
├── destdir
└── sourcedir
    ├── ..d1
    ├── ..d2
    ├── ..double
    ├── file-1
    ├── file-2
    ├── .hidden-1
    ├── .hidden-2
    ├── ...t1
    └── ...t2

Câu hỏi ban đầu chỉ đề cập đến các tệp ẩn với một khoảng thời gian duy nhất, nhưng giả sử có một số có hai hoặc nhiều khoảng thời gian khi bắt đầu tên. Bạn chỉ có thể thêm một biểu thức bổ sung vào dấu ngoặc nhọn. Sau đó chúng ta có thể thực thi

mv sourcedir/{*,.[!.]*,..?*} destdir/

Điều này được mở rộng đến như sau:

mv sourcedir/file-1 sourcedir/file-2 sourcedir/.hidden-1 sourcedir/.hidden-2 sourcedir/..d1 sourcedir/..d2 sourcedir/..double sourcedir/...t1 sourcedir/...t2 destdir/

Bây giờ bạn sẽ thấy tất cả các tệp nằm trong Destdir :

 $ tree -a
.
├── destdir
│   ├── ..d1
│   ├── ..d2
│   ├── ..double
│   ├── file-1
│   ├── file-2
│   ├── .hidden-1
│   ├── .hidden-2
│   ├── ...t1
│   └── ...t2
└── sourcedir

Bạn có thể thực hiện một số điều khá thú vị với niềng răng trong bash với nhiều bổ sung hơn nữa trong 4.x. Hãy xem bash-hackers để biết một số ví dụ tiện lợi.

0
cmndr sp0ck

Bạn cũng có thể tìm và grep với backquote để chọn tệp cho lệnh di chuyển. Truyền những thứ đó vào mv.

I E. Đối với các tập tin ẩn

find Foo -maxdepth 1 | egrep '^Foo/[.]' # Output: .hidden

Vì thế

mv `find Foo -maxdepth 1 | egrep '^Foo/[.]'` Bar # mv Foo/.hidden Bar

Chỉ di chuyển các tệp ẩn được chọn vào Bar:

mv `find Foo -maxdepth 1 | egrep '^Foo/.'` Bar # mv Foo/.hidden Foo/notHidden Bar

Di chuyển tất cả các tệp trong Foo sang Bar kể từ '.' trong lệnh egrep hoạt động như một ký tự đại diện mà không có dấu ngoặc vuông.

Các ^ ký tự đảm bảo trận đấu bắt đầu từ đầu dòng.

Có thể tìm thấy một số chi tiết của egrep khớp mẫu tại đây .

Sử dụng maxdepth 1 dừng tìm thấy đi vào thư mục con.

0
user3192145

Lấy cảm hứng từ câu trả lời này :

Không cần sao chép các tập tin ...

rsync -ax --link-dest=../Foo/ Foo/ Bar

Hãy cẩn thận:

  • --link-dest đường dẫn phải tuyệt đối hoặc liên quan đến DESTINATION (Bar trong ví dụ)

  • Bạn đã đặt / sau NGUỒN (Foo/ trong ví dụ), nếu không, nó sẽ sao chép thư mục SOURCE thay vì nội dung của nó.

0
palindrom