Làm thế nào để di chuyển tất cả các tập tin từ thư mục hiện tại sang thư mục trên trong linux?
Tôi đã thử một cái gì đó như mv *.*
, nhưng nó không hoạt động.
Làm thế nào để di chuyển tất cả các tập tin từ thư mục hiện tại sang thư mục trên trong linux?
Tôi đã thử một cái gì đó như mv *.*
, nhưng nó không hoạt động.
Câu trả lời:
Lệnh bạn đang tìm kiếm là
mv * .[^.]* ..
hoặc (xem bên dưới để biết thêm):
(shopt -s dotglob; mv -- * ..)
Giải thích: mv
lệnh di chuyển các tập tin và thư mục. Đối số cuối cùng mv
là đích (trong trường hợp này là thư mục một bước "lên" trong cây, ..
). Các đối số trước đó là các tập tin nguồn và thư mục. Dấu hoa thị ( *
) là ký tự đại diện khớp với tất cả các tệp không bắt đầu bằng dấu chấm. Các tệp bắt đầu bằng dấu chấm (dotfiles) bị "ẩn". Chúng được kết hợp bằng cách sử dụng mẫu .[^.]*
(xem chỉnh sửa bên dưới).
Xem trang hướng dẫn mà tôi đã liên kết để biết thêm thông tin mv
.
.[^.]*
thay vì .*
?Như Chris Johnsen đã chỉ ra một cách chính xác: mô hình .*
cũng khớp .
và ..
. Vì bạn không muốn (và không thể) di chuyển chúng, tốt hơn là sử dụng một mẫu phù hợp với bất kỳ tên tệp nào bắt đầu bằng một dấu chấm trừ hai cái đó . Mẫu .[^.]*
này thực hiện đúng như vậy: nó khớp với bất kỳ tên tệp (1) nào bắt đầu bằng dấu chấm (2) theo sau là một ký tự không phải là dấu chấm (3) theo sau là 0 hoặc nhiều ký tự tùy ý.
Như Paggas chỉ ra , chúng tôi cũng phải thêm mẫu .??*
để khớp các tệp bắt đầu bằng hai dấu chấm. Xem câu trả lời của anh ấy cho một giải pháp thay thế bằng cách sử dụng find
.
Câu trả lời của Arjan đề cập shopt
để tránh tất cả những vấn đề đó với dotfiles. Nhưng sau đó vẫn còn vấn đề với các tập tin bắt đầu bằng dấu gạch ngang. Và nó đòi hỏi ba lệnh. Tuy nhiên, tôi thích ý tưởng này. Tôi đề nghị sử dụng nó như thế này:
(shopt -s dotglob; mv -- * ..)
Điều này thực thi shopt
trong một lớp con (do đó không shopt
yêu cầu cuộc gọi thứ hai ) và sử dụng --
để các tệp bắt đầu bằng dấu gạch ngang sẽ không được hiểu là đối số mv
.
.*
có thể khiến mv tạo ra các cảnh báo / lỗi về việc không thể di chuyển .
và ..
. Bạn có thể thử mv * .[^.]* ..
thay thế.
Câu trả lời ngắn: sử dụng
find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +
Câu trả lời dài:
Lệnh
mv * .* ..
sẽ không hoạt động vì .*
có thể phù hợp .
và ..
. Nhưng lệnh
mv * .[^.]* ..
cũng sẽ không hoạt động, vì .[^.]*
sẽ không khớp, ví dụ , ..filename
! Thay vào đó, những gì tôi làm là
mv * .[^.] .??* ..
mà sẽ phù hợp với tất cả mọi thứ ngoại trừ .
và ..
. *
sẽ khớp với tất cả mọi thứ không bắt đầu bằng a .
, .[^.]
sẽ khớp với tất cả tên tệp 2 ký tự bắt đầu bằng dấu chấm trừ ..
và .??*
sẽ khớp với tất cả tên tệp bắt đầu bằng dấu chấm có ít nhất 3 ký tự.
Tốt hơn nữa, bạn có thể sử dụng
find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +
trong đó tránh các hack toàn cầu xấu xí trong mv * .[^.] .??* ..
!
..?*
vào nhận xét của mình và bạn đã quan tâm đến nó.
mv
ngừng tìm kiếm bất kỳ tùy chọn lệnh nào nữa. Niềng răng là một tên tệp kết quả. Dấu cộng cho biết thay vì chạy exec trên mỗi kết quả (ví dụ: mỗi tên tệp), hãy đặt càng nhiều kết quả trong một lần thực thi càng tốt. Để hoàn thiện, việc thông báo -t..
di chuyển đích đến để di chuyển tất cả các tệp này sang.
Để hoàn thiện, người ta cũng có thể yêu cầu shell Bash bao gồm các tệp ẩn, sử dụng shopt
:
shopt -s dotglob
mv -- * ..
shopt -u dotglob
Các mv thiếu chức năng di chuyển các tập tin ẩn khi sử dụng *
- vậy tại sao không sử dụng bản sao thay thế?
cp -rf . ..
rm -rf *
Không cần phải đi vào các giải pháp phức tạp của dotglobbing và sử dụng các lệnh find.
cp
và rm
thay vào đó bạn đang thực sự sao chép tất cả.
rsync -a --remove-source-files . ..
rsync
là một công cụ sao chép tệp cực kỳ mạnh mẽ, thường được sử dụng để thực hiện sao lưu từ xa và gương hiệu quả.
Với lệnh trên, chúng tôi đang yêu rsync
cầu sao chép nội dung .
vào..
Công tắc -a
cho phép đệ quy vào các .
thư mục con và cho phép một số tùy chọn phổ biến khác.
Công tắc --remove-source-files
yêu cầu rsync xóa các tệp nguồn sau khi sao chép thành công, tức là nó làm cho rsync hoạt động tương tự như mv
lệnh.
--remove-source-files
sẽ không loại bỏ (đồng bộ hóa) thư mục.
-bash: /bin/mv: Argument list too long
lỗi. Điều này làm việc như sự quyến rũ.
Cuối cùng, việc thử mv .
sẽ thất bại vì mv sẽ không thể hủy liên kết thư mục mà bạn hiện đang ở. Bạn có thể mv * ..
di chuyển các tệp trong cwd.
mv * .??* ../.
*
được tất cả các tập tin không chấm. .??*
được tất cả. các tệp dài ít nhất ba byte, hoạt động cho tất cả các tệp hợp pháp. Bất cứ điều gì còn lại bạn có thể muốn rm
hơn là mv
dù sao.
Việc ../.
này không mang lại bất kỳ lợi ích trực tiếp nào ..
nhưng khi thực hiện chuyển đến thư mục thì đó là một thói quen rất tốt, bởi vì nó sẽ thất bại, như bạn muốn, nếu có gì đó không đúng với đường dẫn. Ví dụ, mv xyz bletch
nơi bạn nghĩ bletch
là một thư mục, có thể được làm chắc chắn hơn với mv xyz bletch/.
.
.[^.]
để có được các tập tin bìa như .a
.
Lệnh thu nhỏ này hoạt động trên hầu hết các shell hiện đại:
\mv -- {,.{[^.],??}}* ..
Mặt khác được đề cập là một giải pháp di động:
\mv -- * .[^.] .??* ..
Đặc trưng:
\ ngăn bí danh thay đổi mv không mong muốn.
- ngăn tên tệp chứa các dấu gạch nối hàng đầu (-xyz) khỏi bị hiểu là đối số dòng lệnh.
. [^.] khớp với tất cả tên tệp của hai ký tự bắt đầu bằng. ngoại trừ ..
. ?? * khớp với tất cả tên tệp khác từ ba ký tự trở lên.
Triển khai ngây thơ:
Sau đây bỏ qua các tên tệp UNIX ẩn, những tên bắt đầu bằng. (.bashrc).
mv * ..
Các kết quả khớp sau đây .. mà đệ quy cố gắng di chuyển mọi thư mục cuối cùng trở lại / vào .. của thư mục làm việc hiện tại ($ PWD hoặc pwd). Không bao giờ sử dụng.
mv .* ..
Sử dụng mô hình chính xác * .[!.] .??*
hơn so với * .[^.] .??*
trước đây cũng sẽ hoạt động với các vỏ cũ hơn như ksh88:
mv -- * .[!.] .??* ..
--
ngăn chặn sự cố khi bạn có tên tệp bắt đầu bằng -
*
khớp với tất cả các tên tệp không bắt đầu bằng .
.
mà bạn có thể / nên di chuyển.[!.]
khớp với tất cả hai tên tệp ký tự bắt đầu bằng .
.??*
khớp với cả ba tên tệp ký tự (hoặc dài hơn) bắt đầu bằng một .
Với ksh88, mẫu tên tệp .[^.]
trên thực tế sẽ khớp với tên tệp ..
(luôn tồn tại) và .^
(có lẽ không tồn tại), có tác động ngược lại với những gì mong muốn.
Tìm và grep làm việc quá. Kiểu cấu trúc này có thể hữu ích nếu bạn muốn chọn các tệp theo tiêu chí phức tạp hơn bằng cách sửa đổi find và egrep.
find -maxdepth 1 | egrep '^./.' # Returns all files
mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..
Tôi nghĩ rằng giải pháp đơn giản nhất để di chuyển tất cả các tập tin vào thư mục mẹ của nó. sẽ là
mv "`ls`" ../
hoặc, nếu có các tập tin / thư mục ẩn
sử dụng:
mv "`ls -a`" ../ 2>/dev/null
Ngoài ra, giả sử bạn muốn di chuyển nội dung của một số thư mục sang một trong các thư mục nội bộ của nó (giả sử)
sử dụng:
mv "`ls -a`" /tony 2>/dev/null
Ghi chú:
"`ls -a`"
Để di chuyển các tập tin có không gian trong đó.
2>/dev/null
Là để chặn cảnh báo / lỗi vì ls -a
cũng sẽ in .
và ..
thư mục và bạn không thể di chuyển hoặc sao chép chúng. Vì vậy, đối với các thư mục đó, nó sẽ hiển thị lỗi (nếu chúng tôi không sử dụng 2> / dev / null) rằng nó không thể di chuyển chúng và phần còn lại sẽ được di chuyển khá thoải mái.
Tốt nhất nên tránh ls -a
nếu không có tập tin ẩn và chỉ sử dụng ls
.
mv $(ls -a)
? Điều đó sẽ nhấn vào thư mục hiện tại và thư mục bên dưới nó, vì ls -a
cũng sẽ xuất ra ..
.
mv ls -a ../
cũng sẽ hoạt động theo nhu cầu, Có, nó sẽ hiển thị các lỗi như tôi đã đề cập ở trên nhưng ngoài ra nó sẽ di chuyển các thư mục / tệp cần thiết vào thư mục gốc.
ls
lệnh để di chuyển tệp có dấu cách. Tôi đã thực hiện các thay đổi cần thiết. Cảm ơn đã chỉ ra.
[linux] [mv] [cwd] [files]
hoặc một cái gì đó tương tự không?