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 YY
jest 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 mv
to 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 mkdir
katalogu. (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 „ mv
skryptlet”, aby uniknąć tego rodzaju najbardziej niechcianych niespodzianek.
.mp3
Powinna tam być przynajmniej jedna z nazwą90
, może to być ta, dla której nie masz kopii zapasowej.mv
nie jest tu problemem, technicznie rzecz biorąc, nie wie, że przenosisz serię plików. Uruchamiaszmv
jeden raz dla każdego pliku. Tak tofind -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.mv
dla 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ść. :)mv
że miejsce docelowe istnieje?mv oldfile newfile
jest sposobem na zmianę nazwy pliku i głupie jest oczekiwanie,newfile
że już istnieje i będzie katalogiem.Odpowiedzi:
Możesz dodać a
/
do miejsca docelowego, jeśli chcesz przenieść pliki do katalogu. Jeśli katalog nie istnieje, pojawi się błąd:Jeśli katalog istnieje, przenosi go do tego katalogu.
źródło
Coreutils GNU
mv
ma już opcję określającą, że chcesz przejść do katalogu:-t
/--target-directory
. Jeśli argument tej opcji nie istnieje,mv
narzeka zamiast przenosić wszystkie pliki pod tą samą nazwą pliku.Napisałbym twój napęd w następujący sposób:
Zwróć uwagę na użycie
+
zamiast\;
globowania jak największej liczby nazw plików razem, co powoduje szybsze wykonanie.źródło
find . -name '* 9?.mp3' -exec sh -c 'exec mv "$@" 90/' sh {} +
Ponadto, jeśli na ogół planujesz uniknąć przypadkowych zastąpień w przyszłości, istnieje
-i
opcjamv
. Osobiście nie mogę wymyślić żadnych wad, jeśli tyJeśli musisz coś zastąpić, po prostu przekaż tę
-f
opcję.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ś bieca następnie zostaniesz poproszony, jeśli
mv
spróbujesz zastąpić istniejący plik.źródło
mv
. Ta mniej znana „sztuczka” spowoduje, że polecenie z poprzedzającym go odwrotnym ukośnikiem zignoruje wszelkie definicje aliasów.find ... -exec mv ...
, musisz utworzyć~/bin/mv
(lub inny odpowiedni katalog) i zrobić to/bin/mv -i "$@"
- bofind ... -exec
nie patrzy na aliasy.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).mv
w miejscu na początku$PATH
byłoby czystszym rozwiązaniem. Z drugiej strony zdarza mi się przede wszystkimmv
niedbale w interaktywnej powłoce (ponieważ dzieje się to szybko). W chwili, gdy komponować coś bardziej skomplikowane, jakfind
czyfor
pętla, lub nawet skrypt powłoki, staram się wykonać kilka suchych działa (używającecho
), aby upewnić się, że nie psuje. W takich przypadkach nie potrzebuję trzymania za rękęmv
, ponieważ już się nad tym zastanawiam.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,
mv
zmieni nazwę Twojego pliku na nową.Problem polega na tym, że używałeś
find
do wykonaniamv
raz na plik , a nie raz dla wszystkich plików .Gdyby to zrobiłeś
mv *90.mp3 90
,mv
nie 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 -i
pytania, czy chcesz zastąpić istniejący plik.źródło
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. Dofind
tej 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, twojamv
linia ma zastosowanie.mv
zachowuje, a nie krytykę twojego wyboru narzędzi.find
imv
np.find /music -type d -exec mv {}/*90.mp3 targetdir\;
- ale teraz czuję się trochę tak, jakbym to nadmiernie-i
-t
find . -type d -exec mv {}/*9?.mp3 target \;
przykład zadziałał, nadal istniałoby ryzyko, żemv
komenda wyglądałabymv file target
dla każdego katalogu zawierającego tylko jeden*9?.mp3
plik; więc wszystkie takie pliki (oprócz ostatniego) zostaną utracone.*.mp3
plikami w drzewie katalogów, możesz,shopt -s globstar
a następnie uruchomić swoje polecenie**/*.mp3
-**
będzie działać jakfind
.Jako alternatywną strategię ogólnego przeznaczenia chciałbym zaproponować przekształcenie tego rodzaju operacji w tymczasowy skrypt. Wolę patrzeć na wyniki
find
i przekształcać je wmv
polecenie ręcznie, upewniając się, że rozumiem, co robię przed wykonaniem. na przykład.Teraz mogę przejrzeć listę nazw plików i przepisać zawartość pliku jako polecenie powłoki.
ggVGJ
Imv
[esc]
Asomedir/
[esc]
source tmp
w wierszu poleceń.Jest to strategia konserwatywna, ale zbyt często gryzły mnie błędne polecenia
-exec
lubsed
polecenia 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
.źródło
:%s/.*/"&"/
krok - ponieważ w tym przypadku wiesz, że każda nazwa pliku zawiera co najmniej jedną spację.echo mv
zamiastmv
, a następnie usuwanie,echo
jeśli jesteś zadowolony.Inna opcja:
jest taki sam jak -i, ale nie zapyta, zawiedzie.
źródło