dotknij wszystkich folderów w katalogu

14

Usiłuję zaktualizować znaczniki czasu wszystkich folderów w cwd przy użyciu tego:

for file in `ls`; do touch $file; done

Ale to nie działa. Jakieś pomysły dlaczego?

javamonkey79
źródło

Odpowiedzi:

21

Wszystkie dotychczasowe odpowiedzi (jak również przykład w pytaniu) zakładają, że chcesz touchwszystko w katalogu, nawet jeśli powiedziałeś „dotknij wszystkich folderów”. Jeśli okaże się, że katalog zawiera pliki i foldery, a chcesz tylko zaktualizować foldery, możesz użyć find:

$ find . -maxdepth 1 -mindepth 1 -type d -exec touch {} +

Lub jeśli Twoja findimplementacja nie obsługuje niestandardowych -mindepth/ -maxdepthpredykatów:

$ find . ! -name . -prune -type d -exec touch {} +

To:

$ touch -c -- */

Powinien działać w większości powłok, z wyjątkiem tego, że:

  • oprócz zwykłych katalogów będzie także touch symlinkował do katalogów
  • pominie te ukryte
  • jeśli nie ma katalog lub dowiązanie symboliczne do katalogu, to utworzyć plik o nazwie *w muszli innych niż csh, tcsh, zsh, fishlub Thompson shell (co byłoby zgłosić błąd zamiast). W tym przypadku używamy -cdo obejścia tego problemu, chociaż nadal może to być touchplik spoza katalogu o nazwie *.

Z zsh, touchtylko do katalogów, w tym ukrytych:

touch -- *(D/)
Michał Mrożek
źródło
O czym jest „{} \ +”?
javamonkey79
3
Jest {} \+to specjalna findskładnia - czytaj stronę podręcznika, aby uzyskać więcej. Myślę, że touch -c ./*/to też zadziała.
jw013,
2
Należy dołączyć -maxdepth 1do polecenia, aby findnie powracało do podfolderów. Wydaje się, że OP chce dotykać tylko tych folderów w cwd, a nie podfolderów.
Steven Poniedziałek,
1
@ jw013 Byłoby - ciągle dołączasz dobre pomysły do ​​odpowiedzi innych ludzi :)
Michael Mrozek
Dlaczego miałbyś uciec od znaku +? Czy istnieją powłoki, które to interpretują?
Witiko
11

Próbować

touch ./*

Unika niepotrzebnej forpętli, która odradzałaby nowy proces dla każdego pliku i działa dla wszystkich nazw plików, nawet tych ze spacjami lub tych, które wyglądają jak opcje (jak -t). Jedyny raz to nie zadziała, jeśli nie masz plików (bez kropek) w katalogu, w którym to przypadku utworzysz plik o nazwie *. Aby tego uniknąć, w konkretnym przypadku touchwiększość implementacji ma -copcję (wywoływaną również --no-createw wersjach GNU), aby nie tworzyć nieistniejących plików, tj.

touch -c ./*

Zobacz także dobre referencje w odpowiedzi jasonwryan jest jak ten jeden .

jw013
źródło
1
Co się stanie, jeśli masz 1 milion folderów na dysku CD?
Steven poniedziałek,
Jeśli napotkasz problemy typu „lista argumentów za długa”, prawdopodobnie najlepiej przełączyć się na „cięższe” narzędzia, takie jak find . -type d -maxdepth1 -print0 | xargs -0 touchlub odpowiedź Michaela Mrożka powyżej.
jw013,
7

Nie powinieneś próbować analizować danych wyjściowychls .

Powinieneś również zacytować swoje, "$file"aby uchwycić dowolne białe znaki. Zobacz http://www.grymoire.com/Unix/Quote.html

Coś takiego może osiągnąć to, czego szukasz:

for file in *; do touch "$file"; done

Zobacz dwa pierwsze pułapki Bash, aby uzyskać dokładniejsze wyjaśnienie.

jasonwryan
źródło
2
Blisko, ale nie do końca. A touch ./*powinno działać w większości przypadków. forPętla nie jest tak naprawdę potrzebna, ponieważ touchmoże zająć wiele plików, a Ty musisz odpowiednio ./obsługiwać pliki o nazwach --help. To dobry zasób na ten temat.
jw013,
Dlaczego „*” działa?
javamonkey79,
@ javamonkey79 To globbing powłoki .
jw013,
1
@ jw013 Doskonały punkt: i dziękuję za link wheeler.
jasonwryan
Pamiętaj, że *nie przechwytuje plików i katalogów, których nazwa zaczyna się od kropki. Jednym ze sposobów rozwiązania tego problemu jest włączenie dotglobopcji powłoki za pośrednictwem shopt -s dotglob.
Witiko
-1
for file in `find .`; do touch $file; done
mikematic
źródło