Jak zapobiec przenoszeniu kolekcji plików „mv” do jednego zwykłego pliku?


17

Właśnie straciłem niewielką część mojej kolekcji audio przez głupi błąd, który popełniłem. :-(
CHRONIONO Miałem dość nową kopię zapasową, ale wciąż była irytująca. Poza twoją naprawdę, innym sprawcą mv, który popełnił błąd, było :

Pliki audio miały pewien schemat:

ARTIST - Some Title YY.mp3

gdzie YYjest dwucyfrowa specyfikacja roku.

mkdir 90<invisible control character>

(Do tej pory nie wiedziałem, że wpisałem jedną trzecią nadmiaru znaku, który był niewidoczny ...!)
Zamiast mieć wszystko w jednym katalogu, chciałem mieć całą muzykę lat 90. w jednym katalogu. Więc napisałem:

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

Nie tak trudno zrozumieć, co się stało, co? : ->
(katastrofalnym) wynikiem był dziewiczy pusty katalog o nazwie „90 coś ” (gdzie coś jest „niewidzialnym” znakiem kontrolnym) i jeden pojedynczy plik o nazwie „90”, nadpisany n razy.

Wszystkie pliki zniknęły. : - (((oczywiście)

Życzenie mvto już sprawdzone w czasie, czy podpis „plik” docelowego (pamiętaj na * nix: Wszystko jest plikiem ) zaczyna się od d------(na przykład drwxr-xr-x). I oczywiście, czy cel w ogóle istnieje . Istnieje wariant wyżej wspomnianego scenariusza, w którym najpierw zapomniałeś o mkdirkatalogu. (ale oczywiście zakładałeś, że tam jest ...)

Nawet nasz pet-nienawiść OS począwszy od kapitału W robi to zrobić. Zostaniesz nawet poproszony o podanie typu miejsca docelowego (plik? Katalog?), Jeśli o to poprosisz.

Dlatego zastanawiam się, czy my * NIXers nadal musimy napisać sobie „ mvskryptlet”, aby uniknąć tego rodzaju najbardziej niechcianych niespodzianek.


2
Nie wszystkie pliki zniknęły. .mp3Powinna tam być przynajmniej jedna z nazwą 90, może to być ta, dla której nie masz kopii zapasowej.
Anthon

2
Hej, masz cyniczne poczucie humoru, wariujesz! :-P Cóż, to był plik o nazwie „jeden pojedynczy plik” pogrubioną czcionką w mojej OP. :)
składniaerror

2
mvnie jest tu problemem, technicznie rzecz biorąc, nie wie, że przenosisz serię plików. Uruchamiasz mvjeden raz dla każdego pliku. Tak to find -exec ;działa. Jeśli użył find -exec +(jak w niektórych komentarzach) mv będzie krzyczeć tak szybko, jak to ma więcej niż jeden argument.
Etan Reisner

Chociaż uruchamianie mvdla każdego pojedynczego pliku może początkowo wydawać się nieco mniej przemyślane, będzie (jak już powiedziałem wcześniej) jedynym rozsądnym rozwiązaniem, gdy pliki źródłowe zostaną rozproszone między różnymi podkatalogami. To, że w moim przypadku testowym wszystkie pliki źródłowe znajdowały się w jednym katalogu, nie oznacza, że ​​to mój rzeczywisty przypadek testowy. W rzeczywistości jest to tylko uproszczenie, ponieważ później mogę z łatwością rozwinąć tę kwestię. Ponadto sprawia, że ​​czytanie jest mniej czasochłonne ze względu na zmniejszoną długość. :)
syntaxerror

Dlaczego miałbyś oczekiwać, mvże miejsce docelowe istnieje? mv oldfile newfilejest sposobem na zmianę nazwy pliku i głupie jest oczekiwanie, newfileże już istnieje i będzie katalogiem.
Barmar

Odpowiedzi:


37

Możesz dodać a /do miejsca docelowego, jeśli chcesz przenieść pliki do katalogu. Jeśli katalog nie istnieje, pojawi się błąd:

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

Jeśli katalog istnieje, przenosi go do tego katalogu.


4
Dziękuję bardzo! To powinien być mój przyszły ratownik. Jestem ci winny przysluge. (Dla przypomnienia, mój przyjaciel popełnił ten sam błąd kilka lat temu, więc wydaje mi się, że nie jestem sam.)
syntaxerror

1
Ponadto, korzystając z niektórych powłok, masz opcję Tab, aby automatycznie uzupełniać nazwy plików. Jeśli nie pamiętam dokładnie nazwy katalogu i nie chcę bałaganu, jaki miałeś ostatnio, po prostu wpisz znak lub dwa w nazwie katalogu i naciśnij TAB . Zatem możesz być pewien, że istnieje, ponieważ umieść go w
autouzupełnianiu

@AndyzSmith Cóż, o to właśnie chodzi. Możesz nazwać to moim nawykiem, że zawsze używaj TAB tylko w przypadku skomplikowanych katalogów lub ścieżek, ale nie w przypadku 2-literowych czcionek. :) Ale pomyśl o tym ... być może powinienem też rozważyć ten drugi przypadek od teraz.
składnia błąd

20

Coreutils GNU mvma już opcję określającą, że chcesz przejść do katalogu: -t/ --target-directory. Jeśli argument tej opcji nie istnieje, mvnarzeka zamiast przenosić wszystkie pliki pod tą samą nazwą pliku.

Napisałbym twój napęd w następujący sposób:

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

Zwróć uwagę na użycie +zamiast \;globowania jak największej liczby nazw plików razem, co powoduje szybsze wykonanie.


Dzięki. (Mam jednak nadzieję, że to już nie jest jeden z tych GNU-izmów).
składniaerror

2
@błąd składni. To jest GNUism. POSIXly:find . -name '* 9?.mp3' -exec sh -c 'exec mv "$@" 90/' sh {} +
Stéphane Chazelas,

Dziękuję bardzo za ten SNEAKY one-liner! Pomyśl tylko, że dałem ci +5. :) Sprawi, że wiele prób prób i błędów stanie się niepotrzebnych .--- I wiesz zbyt dobrze, dlaczego zrobiłem tę uwagę. Po prostu muszę być na komputerze, który jest po prostu POSIX (nie zdarza się to zbyt rzadko), a ja będę miał następny problem. :)
syntaxerror

1
@syntaxerror Jeśli ta odpowiedź rozwiązuje problem, poświęć chwilę i kliknij znacznik wyboru pod liczbą głosów po lewej stronie, będzie to oznaczać dla wszystkich, że problem został rozwiązany i jest to sposób wyrażenia podziękowań w witrynie. Widziałem, że tylko niektóre z pozostałych pytań, na które udzielono odpowiedzi, zaakceptowały odpowiedzi, możesz też je ujawnić.
Anthon

Nie, to po prostu cel. Często czekam kilka tygodni, a czasem 2 miesiące, aż zaakceptuję odpowiedź. Powodem jest to, że niektóre bardzo dobrze poinformowane osoby mają BARDZO załadowany harmonogram i mogą znaleźć czas na udzielenie (zwykle najlepszej) odpowiedzi po kilku tygodniach. Dlatego zawsze uważam, że szanuje mnie tylko czekanie na nich. Cóż, a jeśli naprawdę tego nie zrobią, na pewno nie zawaham się zaznaczyć znacznika wyboru. Poza tym nie rozumiem, dlaczego niektórzy ludzie tak bardzo spieszą się z SE + i jej smakami. Łatwo to robi, chłopaki. Nie podskakuj z pistoletu. :) To nie twój szef naciska na ciebie.
syntaxerror

10

Ponadto, jeśli na ogół planujesz uniknąć przypadkowych zastąpień w przyszłości, istnieje -iopcja mv. Osobiście nie mogę wymyślić żadnych wad, jeśli ty

alias mv='mv -i'

Jeśli musisz coś zastąpić, po prostu przekaż tę -fopcję.

Aliasy działają tylko po wpisaniu polecenia bezpośrednio w interaktywnej powłoce, a nie w przypadkach takich jak wywołanie przez find. Mógłbyś biec

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

a następnie zostaniesz poproszony, jeśli mvspróbujesz zastąpić istniejący plik.


4
Lub - jak zapewne nie wiedziałeś - wpisz ´ \ mv `zamiast mv. Ta mniej znana „sztuczka” spowoduje, że polecenie z poprzedzającym go odwrotnym ukośnikiem zignoruje wszelkie definicje aliasów.
składniaerror

Oczywiście, jeśli naprawdę o tym mówisz find ... -exec mv ..., musisz utworzyć ~/bin/mv(lub inny odpowiedni katalog) i zrobić to /bin/mv -i "$@"- bo find ... -execnie patrzy na aliasy.
G-Man mówi „Przywróć Monikę”

W takim przypadku wolałbym env mv. Mniej pisania. :) Ponieważ mój lokalny układ klawiatury wymaga naciśnięcia klawisza SHIFT, aby wykonać ukośnik do przodu, zawsze preferuję wersje bez ukośnika (jeśli dotyczy).
składniaerror

1
@syntaxerror: BTW, kiedy odpowiadasz na komentarz (w nowym komentarzu), zwykle podaje się nazwisko autora poprzedzone „@”, jak w „@ G-Man”. W ten sposób otrzymuję powiadomienie. (Byłem w stanie odpowiedzieć na twój ostatni komentarz w niepełnym terminie, ponieważ zostałem powiadomiony komentarzem Jenny D.) Możesz skrócić lub użyć całego imienia (bez spacji), np. „@ StéphaneChazelas”. Autor wpisu jest automatycznie powiadamiany o komentarzach do tego wpisu. Zobacz akapity Odpowiedzi w komentarzach na tej stronie pomocy .
G-Man mówi „Przywróć Monikę”

1
Przepraszam, przez jeden dzień nie miałem internetu. @ G-Man Zgadzam się, że posiadanie osobistej wersji mvw miejscu na początku $PATHbyłoby czystszym rozwiązaniem. Z drugiej strony zdarza mi się przede wszystkim mvniedbale w interaktywnej powłoce (ponieważ dzieje się to szybko). W chwili, gdy komponować coś bardziej skomplikowane, jak findczy forpętla, lub nawet skrypt powłoki, staram się wykonać kilka suchych działa (używając echo), aby upewnić się, że nie psuje. W takich przypadkach nie potrzebuję trzymania za rękę mv, ponieważ już się nad tym zastanawiam.
ayekat

7

Oprócz powyższych doskonałych odpowiedzi chciałbym wyjaśnić, dlaczego nie otrzymałeś pytania, czy przenieść pliki, czy nie.

Jeśli przeniesiesz jeden plik na nową nazwę, a ta nazwa nie jest katalogiem, mvzmieni nazwę Twojego pliku na nową.

Problem polega na tym, że używałeś finddo wykonania mvraz na plik , a nie raz dla wszystkich plików .

Gdyby to zrobiłeś mv *90.mp3 90, mvnie powiódłby się komunikat o błędzie, że „plik docelowy nie jest katalogiem”.

Inną radą jest użycie uzupełniania tabulacji podczas wpisywania ścieżki docelowej. Pokaże, czy celem jest katalog, dodając /do nazwy celu. Możesz również użyć mv -ipytania, czy chcesz zastąpić istniejący plik.


Gdybyś to zrobił mv *90.mp3 90, mv nie powiodłby się komunikat o błędzie, że „plik docelowy nie jest katalogiem”. Hah, tak, dlaczego tak skomplikowane, co? Korzystam z twojej linii i będę szczęśliwy. Jednak tylko w tym trywialnym przypadku. :) Ponieważ jest to normalny sposób, zadaję moje pytania: chciałbym je zawęzić dla uproszczenia. Do findtej pory nikt się nie sprzeciwiał , biorąc pod uwagę, że pliki z lat 90-tych mogą równie dobrze być rozproszone w różnych podkatalogach, które również chcę „złapać”. Jeśli i tylko jeśli zawsze w jednym katalogu źródłowym, twoja mvlinia ma zastosowanie.
składniaerror

@syntaxerror Bardzo prawda - miałem na myśli to jako przykład tego, jak się mvzachowuje, a nie krytykę twojego wyboru narzędzi.
Jenny D

1
Prawdopodobnie mógłbyś zbudować coś łączącego find i mvnp. find /music -type d -exec mv {}/*90.mp3 targetdir\;- ale teraz czuję się trochę tak, jakbym to nadmiernie -i-t
Jenny D

1
@Jenny: Jeśli Twój find . -type d -exec mv {}/*9?.mp3 target \;przykład zadziałał, nadal istniałoby ryzyko, że mvkomenda wyglądałaby mv file targetdla każdego katalogu zawierającego tylko jeden *9?.mp3plik; więc wszystkie takie pliki (oprócz ostatniego) zostaną utracone.
G-Man mówi „Przywróć Monikę”

4
@syntaxerror: Pochwalam twój wysiłek ujawnienia istotnej części problemu, a nie cały 42 000 skryptów liniowych, w których występuje. Ale nawet jeśli chciałbyś zrobić coś ze wszystkimi *.mp3plikami w drzewie katalogów, możesz, shopt -s globstara następnie uruchomić swoje polecenie **/*.mp3- **będzie działać jak find.
G-Man mówi „Przywróć Monikę”

1

Jako alternatywną strategię ogólnego przeznaczenia chciałbym zaproponować przekształcenie tego rodzaju operacji w tymczasowy skrypt. Wolę patrzeć na wyniki findi przekształcać je w mvpolecenie ręcznie, upewniając się, że rozumiem, co robię przed wykonaniem. na przykład.

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

Teraz mogę przejrzeć listę nazw plików i przepisać zawartość pliku jako polecenie powłoki.

  • Umieść zawartość pliku w jednym wierszu: ggVGJ
  • Przygotuj: Imv [esc]
  • Dodać: Asomedir/ [esc]
  • Zapisz plik. Przeczytaj to ponownie. Wziąć oddech.
  • Wykonaj source tmpw wierszu poleceń.

Jest to strategia konserwatywna, ale zbyt często gryzły mnie błędne polecenia -execlub sedpolecenia albo źle rozumiane rozszerzenia powłoki i wolę przyjmować powolne, konsekwentne podejście.

Innymi słowy: jestem zbyt tchórzliwy, aby go używać -exec.


1
Pominąłeś :%s/.*/"&"/krok - ponieważ w tym przypadku wiesz, że każda nazwa pliku zawiera co najmniej jedną spację.
G-Man mówi „Przywróć Monikę”

1
To cię ugryzie, jeśli nazwy plików zawierają spacje lub inne znaki specjalne. Musisz je odpowiednio zacytować. Przejrzenie listy poleceń nie jest szczególnie prawdopodobne, aby wykryć błędy. Istnieją znacznie lepsze sposoby przeglądania poleceń przed ich uruchomieniem, takie jak uruchamianie echo mvzamiast mv, a następnie usuwanie, echojeśli jesteś zadowolony.
Gilles „SO- przestań być zły”

Wykrywanie pomyłek takich jak nazwy plików ze spacjami jest dokładnie tym, w czym ta technika pomoże :-)
Tom Rees

0

Inna opcja:

-n, --no-clobber nie zastępuje istniejącego pliku

jest taki sam jak -i, ale nie zapyta, zawiedzie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.