Przenoszenie plików i monitowanie użytkownika, gdy istnieją zduplikowane nazwy:
Jak pokazują odpowiedzi Subv3rsion i Eric Leschinski , -newermt
predykat 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 -exec
wyraż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 -exec
argumentach 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łą find
komendę, działając tak samo jak nowa linia. Mimo że to find
polecenie nie ma nic po tym -exec
wyraż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ń -exec
i 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 -print
wcześ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
srcdir
został już przeniesiony podczas tej samej find
operacji, lub
- (najmniej prawdopodobne) plik o tej samej nazwie został utworzony gdzieś
srcdir
podczas tej samej find
operacji, po przeniesieniu oryginału, ale wystarczająco szybko, aby go znaleźć, gdy find
przejdzie 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/
mv
mv
- Jeśli nie chcesz tego stopnia interaktywności i
mv
zawsze 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
.
mv
akceptuje flagi -b
i, --backup
aby 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 mv
oraz zmiennymi środowiskowymi. Zobacz man mv
szczegół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 -n
i chcesz wiedzieć, które pliki nie zostały przeniesione, ponieważ istniał inny plik o tej samej nazwie, prawdopodobnie najlepszym sposobem jest find
ponowne uruchomienie oryginalnej komendy bez -exec
i 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 touch
innymi 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 -n
nie 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 find
uruchamiania, 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 mv
nie 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 find
lub 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 find
polecenie?
find
predykaty mogą być testami (podobnymi -type
i -newermt
), używanymi do zwracanych wartości, lub działaniami (podobnymi -print
i -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 -a
for i , -o
for lub ) -a
. find
stosuje 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 q
p -a q
find
-type f
Podobnie jak testy, działania oceniają również na prawda lub fałsz. W ten sposób -exec
zgłasza, czy wykonane polecenie zakończyło raportowanie powodzenie (prawda) lub niepowodzenie (fałsz). Mamy ten łańcuch -exec
wyraż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 mv
zgł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 find
zamiast {}
) 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 find
ocenia następne -exec
wyrażenie, które drukuje komunikat ostrzegawczy.
Dalsza lektura