Napisałem skrypt, który usuwa wszystkie oprócz dwóch ostatnich plików w folderze:
#!/bin/bash
ls -1 --quoting-style=shell-always /path/to/some/folder \
| head -n -2 \
| xargs printf -- "'/path/to/some/folder/%s'\n" \
| xargs sudo rm -rf
Ten skrypt będzie wykonywany codziennie jako zadanie crona.
Rozumowanie jest następujące:
Uzyskaj listę wszystkich używanych plików
ls -1
(aby uzyskać jeden plik w wierszu);Usuń dwa ostatnie z listy za pomocą
head -n -2
;Ponieważ
ls
drukuje ścieżki względne, użyjxargs printf
rzeczy, aby dodać ścieżkę folderu i uczynić ją ścieżką bezwzględną;Wyślij je do
sudo rm -rf
za pomocąxargs
.
Każdy ma dostęp do tego folderu, więc każdy może tworzyć i usuwać dowolne pliki w tym folderze.
Problem w tym, że sudo rm -rf
jest straszny. xargs sudo rm -rf
jest niesamowicie przerażający.
Chcę mieć pewność, że nikt nie może uszkodzić innych folderów / systemów, tworząc sprytne pliki do usunięcia (przypadkowo lub celowo). Nie wiem, coś sprytnego jak:
file with / spaces.txt
co może spowodować bardzo przerażające sudo rm -rf /
.
EDYCJA: Mój błąd, nazwy plików nie mogą zawierać /
, więc ten konkretny problem nie miałby miejsca, ale pytanie o to, czy istnieją inne zagrożenia, wciąż pozostaje aktualne.
Dlatego używam --quoting-style=shell-always
, to powinno zapobiec wszelkim sztuczkom z plikami ze spacjami. Ale teraz zastanawiam się, czy ktoś może być wyjątkowo sprytny ze spacjami i cudzysłowami w nazwie pliku.
Czy mój skrypt jest bezpieczny?
Uwaga: Potrzebuję, sudo
ponieważ uzyskuję dostęp do folderu zdalnie (przy użyciu zmapowanego dysku sieciowego mount
) i nie mogłem go uruchomić bez sudo.
printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm
?/
w imię być tworzone staram się osiągnąć ten tuls
dane wyjściowe, jest to już źle napisane polecenie, nawet przy cytowaniu.ls
myślę, że używa także ustawień regionalnych do sortowania, więc nie rozumiem, jaki jest celhead
usuwania ostatnich 2 (chyba że próbujesz się pozbyć.
i..
które iirc nie są dozwolone jako argumentyrm
. Po prostu użyjfind /path/to/folder -type f delete
. I nie,sudo
jeśliOdpowiedzi:
W systemie Linux dowolny znak jest prawidłową nazwą pliku, z wyjątkiem:
\0
(ASCII NUL): używany do zakończenia łańcucha w C/
(ukośnik): używany do rozdzielania ścieżekWięc twoje podejście na pewno nie zadziała w wielu przypadkach, jak możesz sobie wyobrazić, np. Czy obsługuje on newline (
\n
) w nazwie pliku? ( Wskazówka: nie ).Kilka notatek:
ls
; użyj dedykowanych narzędzi (istnieje co najmniej jedno dla większości przypadków użycia)xargs
, sprawdź, czy możesz uciecfind ... -exec
; W większości przypadków będzie dobrze ze tylkofind
samMyślę, że na razie cię to uruchomi. steeldriver podał już pomysł rozdzielony przez NUL w komentarzu (
printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm
), użyj tego jako punktu wyjścia.źródło
find
również, dzięki za sugestię.ls
parsowanie nie powiodło się, np. Czy wziąłeś pod uwagę nowy wiersz w nazwie pliku?head -z
? Brzmi to absurdalnie, ale nie mamman
aniinfo
w moim linuksie kontenera CoreOS ... Nie mogłem też znaleźć w Internecie. Dostajęhead: invalid option 'z'
head
(dostarczany z GNUcoreutils
). Poniżej znajduje się wersja elektroniczna: manpages.ubuntu.com/manpages/xenial/man1/head.1.htmlxargs
obsługuje niektóre cytaty: z pojedynczymi cudzysłowami, podwójnymi cudzysłowami lub odwrotnym ukośnikiem, co pozwala mu akceptować dowolne argumenty¹, ale ze składnią inną niż składnia cytowania powłoki podobnej do Bourne'a.Implementacja GNU,
ls
taka jak na Ubuntu, nie ma trybu cytowania zgodnego zxargs
formatem wejściowym.Jest
ls --quoting-style=shell-always
kompatybilny z powłokami ksh93, bash i zsh, które podają składnię, ale tylko wtedy, gdy dane wyjściowels
są interpretowane przez powłokę w tych samych ustawieniach narodowych, jakls
wtedy, gdy ją wypisuje. Ponadto należy unikać niektórych ustawień regionalnych, takich jak BIG5, BIG5-HKSCS, GBK lub GB18030.Dzięki tym powłokom możesz w rzeczywistości wykonać:
Ale to ma niewielką przewagę nad:
Jedynym przypadkiem, w którym staje się to użyteczne, jest skorzystanie z
-t
opcjils
sortowania plików według mtime / atime / ctime lub-S
/-V
. Ale nawet wtedy równie dobrze możesz użyćzsh
:na przykład, aby posortować pliki według mtime (użyj
oL
dla-S
in
dla-V
).Aby usunąć wszystkie oprócz dwóch ostatnio zmodyfikowanych zwykłych plików:
¹ nadal istnieją pewne ograniczenia długości (
execve()
w niektórychxargs
implementacjach innych niż GNU i znacznie niższe arbitralne), a niektórexargs
implementacje inne niż GNU dławią dane wejściowe zawierające sekwencje bajtów nie tworzące prawidłowych znaków.źródło