Przenoszenie plików i monitowanie użytkownika, gdy istnieją zduplikowane nazwy:
Jak pokazują odpowiedzi Subv3rsion i Eric Leschinski , -newermtpredykat wybiera pliki zmodyfikowane później niż data (i opcjonalny czas) określona jako operand. Aby znaleźć pliki
- w dowolnym miejscu
srcdir(tj. łącznie z podkatalogami, ich podkatalogami itp.)
- ostatnio zmodyfikowano (na przykład) we wrześniu 2014 r
- i przenieś je do
destdir
... możesz uruchomić:
find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -i {} destdir/ \;
W -execwyrażeniu find podaje nazwę pliku znalezioną zamiast {}. ;oznacza, -execże polecenie, które ma zostać wykonane, i wszystkie jego argumenty, zostały podane (w przypadku, gdy kolejne wyrażenia są przekazywane do znalezienia po -execargumentach tego konkretnego predykatu - patrz przykład tego poniżej). ;należy uciec, ponieważ \;nie jest to specjalnie interpretowane przez powłokę. (Bez \, ;zakończyłoby całą findkomendę, działając tak samo jak nowa linia. Mimo że to findpolecenie nie ma nic po tym -execwyrażeniu, nieprzekazanie ;argumentu jest nadal błędem składniowym.)
Jeśli chcesz tylko wyświetlić listę plików - co jest wskazane, jeśli nie masz pewności, jak są przechowywane stare wiadomości e-mail lub jakie inne pliki mogą być obecne - pomiń -execi wszystko po prawej stronie. (W przypadku wiadomości e-mail często wiadomości e-mail z różnych dat są przechowywane w tym samym pliku; dla kogoś w sytuacji opisanej w pytaniu tutaj zalecam sprawdzenie, w jaki sposób są przechowywane przed przeniesieniem jakichkolwiek plików.) Jeśli chcesz wydrukować ich nazwy i przenieść dodaj je -printwcześniej -exec.
mv -i wyświetla monity za każdym razem, gdy plik zostanie zastąpiony w miejscu docelowym, na przykład, jeśli:
- plik o tej samej nazwie istnieje z poprzedniej kopii zapasowej, lub
- plik o tej samej nazwie, ale z innego podkatalogu
srcdirzostał już przeniesiony podczas tej samej findoperacji, lub
- (najmniej prawdopodobne) plik o tej samej nazwie został utworzony gdzieś
srcdirpodczas tej samej findoperacji, po przeniesieniu oryginału, ale wystarczająco szybko, aby go znaleźć, gdy findprzejdzie on przez inny podkatalog.
Inne sposoby wywoływania rm:
Istnieją inne opcje obsługi plików o zduplikowanych nazwach.
- Bez
-i(tj. ) Zwykle nie monitowałby o zatwierdzenie, ale zrobiłby to, gdyby plik docelowy był tylko do odczytu. ( czasami może nawet zastąpić plik tylko do odczytu, na przykład jeśli użytkownik, który go uruchomił, jest właścicielem pliku).mv {} destdir/mvmv
- Jeśli nie chcesz tego stopnia interaktywności i
mvzawsze chcesz (próbować) zastąpić pliki o identycznych nazwach, użyj mv -f.
- Jeśli natomiast chcesz pominąć pliki źródłowe, gdy istnieje już plik docelowy o tej samej nazwie, użyj
mv -n.
mvakceptuje flagi -bi, --backupaby automatycznie zmieniać nazwy plików o identycznych nazwach, które już istnieją w miejscu docelowym. Domyślnie ~jest dodawany w celu utworzenia nazwy kopii zapasowej, a jeśli plik o nazwie i plik z nazwą kopii już istnieją w miejscu docelowym, plik kopii zapasowej jest zastępowany. To ustawienie domyślne można zastąpić opcjami przekazanymi podczas wywoływania mvoraz zmiennymi środowiskowymi. Zobacz man mvszczegóły i przykład poniżej.
Przenoszenie plików i tworzenie kopii zapasowych w przypadku zduplikowanych nazw:
Aby przenieść wszystkie pliki, ~wykonaj kopię zapasową plików o zduplikowanych nazwach za pomocą sufiksu i użyj sufiksów numerowanych, gdy pliki już istnieją (aby uniknąć nadpisania czegokolwiek), uruchom:.~n~.~
find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv --backup=existing {} destdir/ \;
Jeśli pominąłeś pliki o zduplikowanych nazwach i chcesz wiedzieć, które:
Jeśli używasz mv -ni chcesz wiedzieć, które pliki nie zostały przeniesione, ponieważ istniał inny plik o tej samej nazwie, prawdopodobnie najlepszym sposobem jest findponowne uruchomienie oryginalnej komendy bez -execi wszystko po prawej stronie. Spowoduje to wydrukowanie ich nazw.
Spowoduje to również wydrukowanie nazw wszystkich pasujących plików utworzonych od czasu uruchomienia oryginalnej find .... -exec ...komendy, ale w przypadku tej aplikacji zwykle nie będzie żadnych, ponieważ szukasz plików ze starymi czasami modyfikacji. Możliwe jest nadanie plikowi znacznika czasu modyfikacji starszego niż jego rzeczywisty wiek, z touchinnymi mechanizmami, ale wydaje się, że w tym przypadku nie zdarzy się to bez Twojej wiedzy.
Natychmiastowa znajomość pomijania plików z powodu zduplikowanych nazw:
mv -nnie zgłasza ani nie zwraca żadnego specjalnego kodu wyjścia , gdy powstrzymuje się od przeniesienia pliku. Więc jeśli chcesz być natychmiast informowany o pomijanych plikach podczas finduruchamiania, musisz zrobić dla tego osobny krok. Jednym ze sposobów jest:
find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -n {} destdir/ \; \
-exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \;
Kilka prawdopodobnie drobnych względów technicznych: Ostrzega to niepoprawnie, jeśli mvnie uda się skopiować pliku z innego powodu niż istniejący w miejscu docelowym i zakończy raportowanie . Wydaje się to mało prawdopodobne, ale nie jestem pewien, czy to niemożliwe. Potencjalnie cierpi również z powodu wyścigu : ostrzegałby, gdy nie wystąpił prawdziwy błąd, gdyby nowy plik o tej samej nazwie został utworzony w tym samym miejscu w bardzo krótkim czasie po przeniesieniu starego pliku i przed sprawdzeniem, czy sprawdź, czy został usunięty. (Ze względu na zastosowanie, wątpię, czy kiedykolwiek będzie problemem faktycznie występuje.) To może być przepisany sprawdzić cel przedprzeniesienie pliku zamiast po: wtedy warunek wyścigu będzie odnosił się do nowo utworzonych plików docelowych zamiast plików źródłowych. I podczas gdy błędy i ostrzeżenia zgłaszane przez findlub mv(lub [, chociaż nie powinny być, żadne) nie będą zapisywane jako standardowe błędy , nasze ...skipped (exists in...ostrzeżenie jest zapisywane na standardowe wyjście . Zwykle oba pojawiają się na twoim terminalu, ale może to mieć znaczenie, jeśli piszesz.
Podzieliłem to polecenie na dwa wiersze, aby ułatwić czytanie. Można go uruchomić w ten sposób lub można usunąć \znak nowej linii (tj. Podział linii).
Jak działa to findpolecenie?
findpredykaty mogą być testami (podobnymi -typei -newermt), używanymi do zwracanych wartości, lub działaniami (podobnymi -printi -exec), które są często stosowane ze względu na ich skutki uboczne.
Implikuje się, że między wyrażeniami nie podano żadnego operatora (takiego jak -afor i , -ofor lub ) -a. findstosuje ocenę zwarcia dla i i lub . (tj. ) jest prawdziwe tylko wtedy, gdy oba wyrażenia p i q są prawdziwe, więc q nie trzeba oceniać, jeśli p jest fałszywe. Chociaż często nie myślimy o tym w tych kategoriach, dlatego testy muszą być prawdziwe, aby kolejne działania lub testy mogły zostać ocenione. Załóżmy na przykład, że pojawia się katalog. Zwraca wartość false, więc może później pominąć wszystko.p qp -a qfind-type f
Podobnie jak testy, działania oceniają również na prawda lub fałsz. W ten sposób -execzgłasza, czy wykonane polecenie zakończyło raportowanie powodzenie (prawda) lub niepowodzenie (fałsz). Mamy ten łańcuch -execwyrażeń związanych z niejawnymi i :
-exec mv -n {} destdir/ \; -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \;
Próbuje przenieść plik, a jeśli mvzgłosi awarię, zatrzymuje się. Nie chcemy ostrzec o poprawnie pominiętym pliku, jeśli jakiś inny problem polegał na tym, że nie został on przeniesiony.
Ale jeśli to się udało, to wtedy działa na [komendę . Podobnie find, [obsługuje własny rodzaj wyrażeń przekazywanych jako argumenty. [ -f {} ]sprawdza, czy operand po -f(przekazany do niego findzamiast {}) istnieje (i jest zwykłym plikiem), i zwraca albo wartość prawda / sukces, albo fałsz / błąd.
(Statusy wyjścia wielu poleceń najlepiej interpretować jako oznaczające sukces lub porażkę, ale [status istnienia zwykle najlepiej interpretować jako prawda lub fałsz).
Jeśli zostanie [zwrócony false, plik zniknie, więc został przeniesiony, więc nie trzeba nic robić. Ale jeśli [zwróci wartość false, plik nadal istnieje. Następnie findocenia następne -execwyrażenie, które drukuje komunikat ostrzegawczy.
Dalsza lektura