toque todas las carpetas en un directorio

13

Estoy tratando de actualizar las marcas de tiempo de todas las carpetas en el cwd usando esto:

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

Pero no parece funcionar. Alguna idea de por qué?

javamonkey79
fuente

Respuestas:

21

Todas las respuestas hasta el momento (así como su ejemplo en la pregunta) asumen que quiere touchtodo en el directorio, aunque haya dicho "tocar todas las carpetas". Si resulta que el directorio contiene archivos y carpetas y solo desea actualizar las carpetas, puede usar find:

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

O si su findimplementación no admite los predicados -mindepth/ no estándar -maxdepth:

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

Esta:

$ touch -c -- */

Debería funcionar en la mayoría de los depósitos, excepto que:

  • También hará touch enlaces simbólicos a directorios además de directorios simples
  • omitirá los ocultos
  • si no hay un directorio o enlace simbólico al directorio, se crearía un archivo llamado *en los depósitos distintos csh, tcsh, zsh, fisho la cáscara de Thompson (que informar de un error en su lugar). Aquí, estamos usando -cpara solucionarlo, aunque todavía podría touchllamarse un archivo que no sea de directorio *.

Con zsh, touchsolo a directorios, incluidos los ocultos:

touch -- *(D/)
Michael Mrozek
fuente
¿De qué se trata el '{} \ +'?
javamonkey79
3
La sintaxis {} \+especial es find: lea la página del manual para obtener más información. Creo touch -c ./*/que también funcionaría.
jw013
2
Debe incluir -maxdepth 1el comando para que findno se repita en subcarpetas. OP parece querer tocar solo esas carpetas en el cwd, no las subcarpetas.
Steven lunes
1
@ jw013 Sería - sigues adjuntando buenas ideas a las respuestas de otras personas :)
Michael Mrozek
¿Por qué escaparías del personaje +? ¿Hay conchas que lo interpretan?
Witiko
11

Tratar

touch ./*

Evita el forbucle innecesario que generaría un nuevo proceso para cada archivo y funciona para todos los nombres de archivos, incluso los que tienen espacios o los que parecen opciones (como -t). El único momento en que no funcionaría es si no tiene archivos (que no sean puntos) en el directorio, en cuyo caso terminaría creando un archivo con el nombre *. Para evitar eso, para el caso específico de la touchmayoría de las implementaciones tenemos una -copción (también llamada --no-createen versiones GNU) para no crear archivos inexistentes, es decir

touch -c ./*

Ver también las referencias buenas de la respuesta de jasonwryan así como este uno .

jw013
fuente
1
¿Qué sucederá si tiene 1 millón de carpetas en el cwd?
Steven lunes
Si se encuentra con problemas de tipo "lista de argumentos demasiado larga", probablemente sea mejor cambiar a herramientas "más pesadas" como find . -type d -maxdepth1 -print0 | xargs -0 touch, o la respuesta de MichaelMrozek anterior.
jw013
7

No debe intentar analizar la salida dels .

Además, debe citar su "$file"para capturar cualquier espacio en blanco. Ver http://www.grymoire.com/Unix/Quote.html

Algo como esto podría lograr lo que buscas:

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

Vea las dos primeras trampas de Bash para una explicación más completa.

jasonwryan
fuente
2
Cerca pero no del todo. A touch ./*debería funcionar en la mayoría de los casos. Realmente no hay necesidad del forbucle ya que touchpuede tomar múltiples archivos, y usted necesita ./manejar archivos con nombres como --helpcorrectamente. Este es un buen recurso sobre el tema.
jw013
¿Por qué funciona '*'?
javamonkey79
@ javamonkey79 shell Es globbing .
jw013
1
@ jw013 Excelente punto: y gracias por el enlace de Wheeler.
jasonwryan
Tenga en cuenta que *no captura archivos y directorios cuyo nombre comienza con un punto. Una forma de arreglar eso es habilitar la dotglobopción de shell a través de shopt -s dotglob.
Witiko
-1
for file in `find .`; do touch $file; done
mikematic
fuente