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?

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/)

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 .


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.


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.