Làm cách nào để ngăn `mv` chuyển bộ sưu tập tệp thành một tệp thông thường?


17

Tôi vừa bị mất một phần nhỏ trong bộ sưu tập âm thanh của mình, bởi một sai lầm ngu ngốc mà tôi đã mắc phải. :-(
GLADLY Tôi đã có một bản sao lưu khá gần đây, nhưng nó vẫn gây khó chịu. Ngoài bạn thực sự, thủ phạm khác làm điều sai trái là mv, sẽ hiển thị như sau:

Các tập tin âm thanh có một sơ đồ nhất định:

ARTIST - Some Title YY.mp3

thông YYsố kỹ thuật năm gồm 2 chữ số.

mkdir 90<invisible control character>

(Cho đến thời điểm này, tôi không biết rằng tôi thực sự đã gõ một phần ba ký tự dư thừa vô hình ...!)
Thay vì có tất cả trong một thư mục, tôi muốn có tất cả nhạc trong thập niên 1990 trong một thư mục. Vì vậy, tôi đã gõ:

find . -name '* 9?.mp3' -exec mv {} 90 \;

Không quá khó để có được ý tưởng những gì đã xảy ra nhỉ? : ->
Kết quả (thảm họa) là một thư mục trống rỗng có tên '90 gì đó '(với thứ gì đó là ký tự điều khiển "vô hình") và một tệp duy nhất gọi là' 90 ', được ghi đè lên n lần.

TẤT CẢ CÁC PHIM ĐÃ ĐƯỢC. :-(( (chắc chắn)

Wish mvsẽ kiểm tra kịp thời xem chữ ký của "tệp" đích (nhớ trên * NIX: Mọi thứ là tệp ) có bắt đầu bằng d------(ví dụ drwxr-xr-x) không. Và, tất nhiên, liệu đích đến có tồn tại không. Có là một biến thể của kịch bản nói trên, khi bạn chỉ đơn giản là quên để mkdirthư mục đầu tiên. (nhưng tất nhiên, bạn cho rằng nó ở đó ...)

Ngay cả hệ điều hành ghét thú cưng của chúng tôi bắt đầu từ thủ đô W DOES DO NÀY. Bạn thậm chí còn được nhắc chỉ định loại đích (tệp? Thư mục?) Nếu bạn yêu cầu.

Do đó, tôi tự hỏi nếu chúng ta * NIXers vẫn phải tự viết cho mình một " mvscriptlet" chỉ để tránh những loại bất ngờ không mong muốn này.


2
Không phải tất cả các tập tin đã biến mất. Ít nhất một cái .mp3nên có ở đó với cái tên 90, nó có thể là một cái mà bạn không có bản sao lưu.
Anthon

2
Heh, bạn có một khiếu hài hước hoài nghi, bạn nut bạn! :-P Chà, đó là tệp được gọi là "một tệp duy nhất" được in đậm trong OP của tôi. :)
cú pháp

2
mvKhông phải là vấn đề ở đây, về mặt kỹ thuật, nó không biết rằng bạn đang di chuyển một loạt các tệp. Bạn đang chạy mvmột lần cho mỗi tệp. Đó là cách làm find -exec ;việc. Nếu bạn đã sử dụng find -exec +(như trong một số ý kiến) mv sẽ hét lên ngay khi nó có nhiều hơn một đối số.
Etan Reisner

Mặc dù lúc đầu chạy mvcho mỗi tệp đơn lẻ có vẻ ít suy nghĩ hơn, nhưng nó sẽ (như tôi đã nói trước đây) là giải pháp lành mạnh duy nhất một khi các tệp nguồn nằm rải rác giữa các thư mục con khác nhau. Trong trường hợp thử nghiệm của tôi, các tệp nguồn đều nằm trong một thư mục không có nghĩa đó là trường hợp thử nghiệm thực tế của tôi . Thực tế nó chỉ là một sự đơn giản hóa, bởi vì sau này tôi có thể dễ dàng xây dựng nó. Thêm vào đó, nó làm cho các câu hỏi ít tốn thời gian hơn để đọc do độ dài giảm. :)
cú pháp

Tại sao bạn muốn mvyêu cầu điểm đến tồn tại? mv oldfile newfilelà cách để đổi tên một tập tin và thật ngớ ngẩn khi mong đợi newfiletồn tại và trở thành một thư mục.
Barmar

Câu trả lời:


37

Bạn có thể nối thêm một /điểm đến nếu bạn muốn di chuyển tệp vào một thư mục. Trong trường hợp thư mục không tồn tại, bạn sẽ nhận được một lỗi:

mv somefile somedir/
mv: cannot move ‘somefile’ to ‘somedir/’: Not a directory

Trong trường hợp thư mục tồn tại, nó di chuyển tệp vào thư mục đó.


4
Cảm ơn bạn rất nhiều! Đó nên là người cứu rỗi tương lai của tôi sau đó. Tôi nợ bạn một cái. (Cũng như một ghi chú, một người bạn của tôi đã mắc lỗi tương tự vài năm trước, vì vậy tôi cảm thấy mình không cô đơn.)
cú pháp từ

1
Ngoài ra, khi sử dụng một số Shell nhất định, bạn có tùy chọn Tab để tự động hoàn thành tên tệp cho bạn. Nếu tôi không thể nhớ tên thư mục và không muốn có một mớ hỗn độn như bạn đã có gần đây, chỉ cần bấm vào một hoặc hai ký tự tên thư mục và HIT TAB . Sau đó, bạn có thể chắc chắn rằng nó tồn tại, vì tự động hoàn thành đặt nó ở đó ....
Andyz Smith

@AndyzSmith Vâng, đó là điều rất. Bạn có thể gọi đó là thói quen của tôi khi chỉ sử dụng TAB cho các thư mục hoặc đường dẫn phức tạp , nhưng không phải cho các loại 2 chữ cái. :) Nhưng hãy nghĩ về nó ... có lẽ tôi cũng nên xem xét trường hợp sau từ giờ trở đi.
cú pháp

20

Các lõi GNU mvđã có một tùy chọn chỉ định rằng bạn muốn chuyển đến một thư mục: -t/ --target-directory. Nếu đối số cho tùy chọn đó không tồn tại, mvsẽ khiếu nại thay vì chuyển tất cả các tệp của bạn sang cùng tên tệp.

Tôi đã có thể viết động lực của bạn như sau:

find . -name '* 9?.mp3' -exec mv -t 90 {} +

Lưu ý việc sử dụng +thay vì \;, ghép càng nhiều tên tệp với nhau càng tốt, dẫn đến thực thi nhanh hơn.


Cảm ơn. (Tuy nhiên, hy vọng nó không phải là một trong những GNU-isms nữa.)
cú pháp từ

2
@lỗi cú pháp. Nó là một chủ nghĩa GNU. POSIXly:find . -name '* 9?.mp3' -exec sh -c 'exec mv "$@" 90/' sh {} +
Stéphane Chazelas

Cảm ơn bạn rất nhiều vì điều này nhất SNEAKY! Chỉ cần nghĩ rằng đó là +5 tôi đã cho bạn. :) Sẽ khiến nhiều lần thử và lỗi không cần thiết .--- Và bạn biết quá rõ tại sao tôi lại đưa ra nhận xét đó. Chỉ cần sử dụng máy POSIX (không xảy ra quá hiếm khi xảy ra) và tôi sẽ gặp vấn đề tiếp theo ngay tại đó. :)
cú pháp

1
@syntaxerror Nếu câu trả lời này giải quyết vấn đề của bạn, vui lòng dành một phút và nhấp vào dấu kiểm bên dưới số phiếu ở bên trái, điều này sẽ biểu thị cho mọi người rằng vấn đề của bạn đã được giải quyết và là cách cảm ơn được thể hiện trong trang web. Tôi thấy rằng chỉ có một vài câu hỏi trả lời khác của bạn đã chấp nhận câu trả lời, bạn cũng có thể muốn trả lời những câu hỏi đó.
Anthon

Không, đó chỉ đơn giản là mục đích. Tôi thường đợi vài tuần hoặc đôi khi 2 tháng cho đến khi tôi chấp nhận câu trả lời. Lý do là một số người rất am hiểu có lịch trình RẤT NHIỀU và có thể chỉ tìm thấy thời gian để đưa ra câu trả lời (thường là tốt nhất) sau vài tuần. Vì vậy, tôi luôn thấy nó chỉ tôn trọng để chờ họ dừng lại. Chà, và nếu họ thực sự không, chắc chắn tôi sẽ không ngần ngại đánh dấu chọn. Ngoài ra, tôi không thấy lý do tại sao một số người luôn vội vàng với hương vị của SE +. Dễ dàng làm điều đó, fellas. Đừng nhảy súng. :) Đây không phải là ông chủ của bạn nhấn vào bạn.
cú pháp

10

Ngoài ra, nếu bạn thường có kế hoạch tránh việc ghi đè ngẫu nhiên trong tương lai, có -itùy chọn cho mv. Cá nhân tôi không thể nghĩ ra bất kỳ nhược điểm nào nếu bạn

alias mv='mv -i'

Nếu sau đó bạn cần ghi đè lên một cái gì đó, chỉ cần vượt qua -ftùy chọn.

Bí danh chỉ có hiệu lực nếu bạn nhập lệnh trực tiếp vào hệ vỏ tương tác, không áp dụng cho các trường hợp như gọi bằng find. Bạn có thể đã chạy

find . -name '* 9?.mp3' -exec mv -i {} 90 \;

và sau đó bạn sẽ được nhắc nếu mvđã cố ghi đè lên một tệp hiện có.


4
Hoặc - như bạn có thể không biết - thay vào đó là gõ \ mv ` mv. "Thủ thuật" ít được biết đến này sẽ khiến lệnh có dấu gạch chéo ngược được đặt trước nó bỏ qua mọi định nghĩa bí danh.
cú pháp

Tất nhiên, nếu bạn thực sự đang nói về find ... -exec mv ..., thì bạn sẽ cần phải tạo ~/bin/mv(hoặc một số thư mục phù hợp khác) và thực hiện nó /bin/mv -i "$@"- bởi vì find ... -execkhông nhìn vào bí danh.
G-Man nói 'Tái lập Monica'

Trong trường hợp này, tôi thích env mv. Ít gõ. :) Vì cách bố trí bàn phím cục bộ của tôi yêu cầu nhấn phím Shift cho dấu gạch chéo về phía trước, tôi sẽ luôn ưu tiên các phiên bản "gạch chéo" (nếu có).
cú pháp

1
@syntaxerror: BTW, khi bạn trả lời bình luận (trong một bình luận mới), thông thường phải đề cập đến tên của tác giả, trước đó là từ @ @ @, như trong Chú @ G-Man. Bằng cách đó tôi nhận được thông báo. (Tôi đã có thể trả lời bình luận cuối cùng của bạn một cách bán kịp thời vì tôi đã nhận được thông báo bởi nhận xét của Jenny D.) Bạn có thể viết tắt hoặc sử dụng toàn bộ tên (không có dấu cách), ví dụ, từ @ StéphaneChazelas. Tác giả của một bài viết được tự động thông báo ý kiến ​​cho bài viết đó. Xem phần Trả lời trong các đoạn bình luận của trang trợ giúp này .
G-Man nói 'Phục hồi Monica'

1
Tôi xin lỗi, tôi đã không có Internet trong một ngày. @ G-Man Tôi đồng ý rằng có một phiên bản cá nhân mvở một địa điểm khi bắt đầu $PATHsẽ là một giải pháp sạch hơn. Mặt khác, tôi chủ yếu xảy ra mvbất cẩn trong vỏ tương tác (vì nó xảy ra nhanh). Khoảnh khắc tôi soạn một thứ gì đó phức tạp hơn, như findhoặc một forvòng lặp, hoặc thậm chí là một kịch bản shell, tôi có xu hướng thực hiện một số hoạt động khô (sử dụng echo) để đảm bảo tôi không phá vỡ thứ gì đó. Trong những trường hợp đó, tôi không cần cầm tay mv, vì tôi đã đặt một vài suy nghĩ vào đó.
ayekat

7

Ngoài các câu trả lời xuất sắc ở trên, tôi muốn làm rõ lý do tại sao bạn không nhận được câu hỏi về việc có nên di chuyển các tệp hay không.

Nếu bạn di chuyển một tệp sang một tên mới và tên đó không phải là một thư mục, mvsẽ đổi tên tệp của bạn thành tên mới.

Vấn đề ở đây là bạn đã sử dụng findđể thực thi mvmột lần cho mỗi tệp chứ không phải một lần cho tất cả các tệp .

Thay vào đó, nếu bạn đã hoàn thành mv *90.mp3 90, thì mvsẽ thất bại với thông báo lỗi rằng "tệp đích không phải là một thư mục".

Một lời khuyên khác là sử dụng hoàn thành tab khi gõ đường dẫn đích. Nó sẽ cho bạn biết liệu mục tiêu có phải là một thư mục hay không bằng cách thêm /vào tên đích. Bạn cũng có thể sử dụng mv -iđể được hỏi liệu bạn có muốn ghi đè lên một tệp hiện có hay không.


Thay vào đó, nếu bạn đã hoàn thành mv *90.mp3 90, thì mv sẽ thất bại với thông báo lỗi rằng "tệp đích không phải là một thư mục". Hah, yeah, tại sao quá phức tạp nhỉ? Tôi sử dụng dòng của bạn và tôi sẽ được hạnh phúc. Chỉ trong trường hợp tầm thường này, mặc dù. :) Bởi vì đây là cách thông thường tôi đặt câu hỏi của mình: Tôi muốn thu hẹp chúng vì đơn giản. Cho đến nay, không ai phản đối findrằng các tệp của thập niên 90 cũng có thể nằm rải rác trong các thư mục con khác nhau mà tôi muốn "bắt". Nếu và chỉ khi chúng luôn nằm trong một thư mục nguồn, mvdòng của bạn có thể áp dụng được.
cú pháp

@syntaxerror Rất đúng - Tôi muốn nói điều này như một ví dụ về cách mvcư xử, không phải là một lời chỉ trích về sự lựa chọn công cụ của bạn.
Jenny D

1
Bạn có thể có thể xây dựng một cái gì đó kết hợp findmv, ví dụ find /music -type d -exec mv {}/*90.mp3 targetdir\;- nhưng bây giờ tôi cảm thấy hơi giống như tôi đang áp dụng nó quá mức, và chỉ đơn giản là sử dụng -ihoặc -thiệu quả hơn
Jenny D

1
@Jenny: Nếu find . -type d -exec mv {}/*9?.mp3 target \;ví dụ của bạn hoạt động, vẫn có nguy cơ mvlệnh sẽ giống như mv file targetđối với mỗi thư mục chỉ chứa một *9?.mp3tệp; vì vậy tất cả các tệp như vậy (ngoại trừ tệp cuối cùng) sẽ bị mất.
G-Man nói 'Tái lập Monica'

4
@syntaxerror: Tôi hoan nghênh nỗ lực của bạn để phơi bày phần thiết yếu của vấn đề của bạn, thay vì toàn bộ tập lệnh 42.000 trong đó xảy ra. Nhưng, ngay cả khi bạn đã muốn làm một cái gì đó cho tất cả *.mp3các tệp trong cây thư mục, bạn có thể shopt -s globstarvà sau đó chạy lệnh của bạn **/*.mp3- ý **chí sẽ hoạt động như một find.
G-Man nói 'Phục hồi Monica'

1

Là một chiến lược có mục đích chung thay thế, tôi muốn đề xuất biến loại hoạt động này thành một kịch bản tạm thời. Tôi thích nhìn vào kết quả findvà biến chúng thành một mvlệnh bằng tay, đảm bảo rằng tôi hiểu những gì tôi đang làm trước khi tôi thực hiện. ví dụ.

find . -name '* 9?.mp3' > tmp
vim tmp

Bây giờ tôi có thể xem qua danh sách tên tệp và viết lại nội dung tệp dưới dạng lệnh shell.

  • Đặt nội dung tệp trên một dòng: ggVGJ
  • Chuẩn bị: Imv [esc]
  • Nối: Asomedir/ [esc]
  • Lưu các tập tin. Đọc lại lần nữa. Hãy hít thở.
  • Thực hiện source tmptrên dòng lệnh.

Đó là một chiến lược bảo thủ, nhưng tôi đã bị cắn quá thường xuyên bởi sai lầm -exechoặc sedmệnh lệnh, hoặc mở rộng vỏ bị hiểu lầm, và tôi thích thực hiện một cách tiếp cận nhất quán chậm.

Nói cách khác: Tôi quá hèn nhát khi sử dụng -exec.


1
Bạn bỏ qua :%s/.*/"&"/bước - bởi vì, trong trường hợp này, bạn biết rằng mỗi tên tệp chứa ít nhất một khoảng trắng.
G-Man nói 'Phục hồi Monica'

1
Điều này sẽ cắn bạn nếu tên tệp chứa khoảng trắng hoặc các ký tự đặc biệt khác. Bạn cần trích dẫn chúng đúng cách. Xem lại danh sách các lệnh không có khả năng bắt lỗi. Có nhiều cách tốt hơn để xem lại các lệnh trước khi chạy chúng, chẳng hạn như chạy echo mvthay vì mv, sau đó xóa echonếu bạn hài lòng.
Gilles 'SO- ngừng trở nên xấu xa'

Phát hiện ra một lỗi như tên tệp có dấu cách chính xác là những gì kỹ thuật này sẽ giúp với :-)
Tom Rees

0

Một lựa chọn khác:

-n, --no-clobber không ghi đè lên tệp hiện có

Nó giống như -i, nhưng nó sẽ không hỏi, nó sẽ thất bại.

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.