Usuń wszystkie oprócz 1000 losowych plików z katalogu

13

Zezwalam, aby skrypt generowania danych działał zbyt długo, ma teraz ponad 200 000 plików, których potrzebuję do około 1000. Z wiersza poleceń Linuksa istnieje prosty sposób na usunięcie wszystkich oprócz 1000 tych plików, w których pliki zostałyby zachowane nie miałby zależności od nazwy pliku lub innego atrybutu?

Malcolm Regan
źródło
Czy proces, który utworzył pliki, miał cechę, która powiązała każdy plik z poprzednim? Jeśli tak, to wybranie losowe byłoby ważne, aby uzyskać reprezentatywną próbkę. Jeśli proces generował pliki losowe z natury, możesz po prostu usunąć wszystko po pierwszych 1000.
fixer1234

Odpowiedzi:

15

Usuń wszystkie oprócz 1000 losowych plików z katalogu

Kod:

find /path/to/dir -type f -print0 | sort -zR | tail -zn +1001 | xargs -0 rm

Wyjaśnienie:

  1. Wyświetl wszystkie pliki za /path/to/dirpomocą find;
    • print0: użyj \0( znak null ) jako separatora wiersza; więc ścieżki do plików zawierające spacje / znaki nowej linii nie psują skryptu
  2. Potasuj listę plików za pomocą sort;
    • -z: użyj \0(znak null) jako separatora zamiast \n(nowa linia)
    • -R: losowe zamówienie
  3. Usuń pierwsze 1000 wierszy z losowej listy za pomocą tail;
    • -z: traktuj listę jako rozdzielaną zerami (tak samo jak w przypadku sort)
    • -n +1001: pokaż linie zaczynające się od 1001 (tzn. pomiń pierwsze 1000 linii)
  4. xargs -0 rm - usuń pozostałe pliki;
    • -0: ponownie zero

Dlaczego jest lepszy niż rozwiązanie quixotic *:

  1. Działa z nazwami plików zawierającymi spacje / znaki nowej linii.
  2. Nie próbuje tworzyć żadnych katalogów (które mogą już istnieć, btw.)
  3. Nie przenosi żadnych plików, nie dotyka nawet 1000 „szczęśliwych plików” oprócz ich listy find.
  4. Unika pomijania pliku w przypadku, gdy z jakiegoś powodu wynik findnie kończy się na \n(nowa linia).

* - zasługa quixotic za | sort -R | head -1000, dała mi punkt wyjścia.

rld.
źródło
Działając na CentOS 6 otrzymywałem błędy dotyczące nieprawidłowych operandów. Na szczęście nie interesują mnie spacje w ścieżkach plików, więc usunięcie tych operandów zadziałało dla mniefind . -type f | sort -R | tail -n +1001 | xargs rm
Brad
@brad Czy możesz podać komunikaty o błędach i swoją wersję find? Spróbuję poprawić swoją odpowiedź, po prostu potrzebuję trochę wkładu do pracy.
rld.
3
tail: invalid option -- 'z'wersja ogona, którą mam, to 8.4
Brad
Dodałbym - no-run-if-empty do xargs, aby uniknąć błędu, jeśli nie ma pliku (po dwukrotnym uruchomieniu np.)
fraff
1

Użyj katalogu tymczasowego, a następnie findwszystkich plików, losowo za pomocą listy sortprzenieś górne 1000 listy do katalogu tymczasowego. Usuń resztę, a następnie przenieś pliki z powrotem do katalogu tymczasowego.

$ mkdir ../tmp-dir
$ find . -type f | sort -R | head -1000 | xargs -I "I" mv I ../tmp-dir/
$ rm ./*
$ mv ../tmp-dir/* .

Jeśli xargsnarzekasz na długość linii, użyj mniejszej liczby za pomocą headi powtórz polecenie w razie potrzeby (tj. Zmień -1000go -500i uruchom dwa razy lub zmień -200i uruchom go 5 razy).

Nie będzie również obsługiwać nazw plików zawierających spacje; jak @ odpowiedziami RLD w pokazach, można użyć find„s -print0argument, -zargumenty sorti head, i -0ze xargsw celu zapewnienia właściwej obsługi nazw plików.

Wreszcie, jeśli tmp-dirjuż istnieje, należy zastąpić nazwę katalogu, który nie istnieje.

donkiszotowski
źródło
Nie powiedzie się, jeśli którykolwiek z nazw plików wymienionych przez findzawiera spację.
rld.
0

Użytkownicy komputerów Mac powinni wykonać następujący skrypt.

find . -type f -print0 | tr '\0' '\n' | sort -R | tail -n +10000 | tr '\n' '\0' | xargs -0 rm

trpozwoli sortowaniu i ogonowi działać na listach z \nzamiast \0.

Luca Di Liello
źródło
-2

Najłatwiej może być rm -rf katalogu, a następnie ponownie uruchomić skrypt generowania danych, upewniając się, że nie będzie działać zbyt długo.

Lars Poulsen
źródło
Nie o to pytał OP. Może to nie jest możliwe.