archivos ocultos cp con patrones glob


13

Situación:

$ mkdir foo && touch foo/.test
$ cp foo/* .
zsh: no matches found: foo/*
(or bash : cp: cannot stat foo/*’: No such file or directory)

Tengo un directorio lleno de carpetas y archivos ocultos. ¿Qué está pasando y cuál es la solución?


dotglobes traducido globdotspor zsh, que es un nombre de opción no válido para bash .

Respuestas:


19

Descargo de responsabilidad: ¡Esta respuesta trata específicamente de Bash, pero gran parte se aplica a la pregunta sobre los patrones globales!

El personaje estrella ( *) es un comodín. Hay un cierto conjunto de caracteres que tomará el lugar y el primer carácter que es un punto ( .) no es uno de ellos. Este es un caso especial solo por cómo funcionan los sistemas de archivos Unix, los archivos que comienzan con un punto se consideran "ocultos". Eso significa que las herramientas tales como cp, ls, etc., no va a "ver" a menos que explícitamente se diga que lo haga.

Ejemplos

Primero creemos algunos datos de muestra.

$ mkdir .dotdir{1,2} regdir{1,2}
$ touch .dotfile{1,2} regfile{1..3}

Entonces ahora tenemos lo siguiente:

$ tree -a
.
|-- .dotdir1
|-- .dotdir2
|-- .dotfile1
|-- .dotfile2
|-- regdir1
|-- regdir2
|-- regfile1
|-- regfile2
`-- regfile3

Ahora juguemos algunos juegos. Puede usar el comando echopara enumerar qué sería un comodín particular ( *) para un comando dado de la siguiente manera:

$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3


$ echo reg*
regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2

$ echo .* *
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .dotdir*
.dotdir1 .dotdir2

¿Cambiar el comportamiento?

Puede usar el comando shopt -s dotglobpara cambiar el comportamiento del *archivo de modo que, además de archivos como regfile1este, también coincidan .dotfile1.

extracto de la bashpágina del manual

dotglob If set, bash includes filenames beginning with a `.' in the results 
        of pathname expansion.

Ejemplo:

$ shopt -s dotglob
$ echo *
.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

Puede revertir este comportamiento con este comando:

$ shopt -u dotglob
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3

¿Tu situación?

Para ti, estás diciendo cpque quieres copiar todos los archivos que coinciden con el patrón *, y no hay ningún archivo.

$ cp foo/.* .

O puede hacer esto si quiere todo en la foocarpeta:

$ cp foo .

O puedes ser explícito:

$ cp foot/.* foo/* .

Una forma más compacta con expansión de llaves en bash:

$ cp foo/{.,}* .

En cualquier momento puede usar el echotruco para ver cuáles son los patrones de archivo propuestos (ese es el término elegante para saber de qué forma parte la estrella).

$ echo {.,}*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 abc regdir1 regdir2 regfile1 regfile2 regfile3

Por cierto, si va a copiar un directorio de archivos + otros directorios, normalmente desea hacer esto de forma recursiva, ese es el -Rcambio a cp:

$ cp -R foo/. .

1
Es posible que desee mencionar el uso de shopt -s dotglob, echo *luego da:.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
Drav Sloan

@DravSloan: gracias por la sugerencia. Lo agregó
slm

cp -r foo .Por lo general, no funcionará, ya que cpse negará a copiarse foosobre sí mismo cp -R foo/. .. (tenga en cuenta que cp -Res el estándar).
Stéphane Chazelas

1
También tenga en cuenta que (con bastante sensatez), zshno incluye .y ..en la expansión de .*. En zsh, si un patrón no coincide, el comando se cancela (de manera bastante sensata), por lo que, en el caso general, cp foo/{,.}* .fallará si no hay archivos ocultos o no ocultos.
Stéphane Chazelas

77
Esta respuesta se aplica solo a bash. El autor de la pregunta está usando zsh, donde la respuesta es mucho más simple y shoptno existe.
Gilles 'SO- deja de ser malvado'

29

Con zsh, la forma típica es usar el D calificador glob (para incluir [D] ot archivos):

cp foo/*(D) .

Tenga en cuenta que con o sin D, los globos zsh nunca incluyen .ni ..(como era de esperar).


4

El shell trata esos archivos como ocultos cuando resuelve el *carácter, por lo cpque no recibe ninguno de estos nombres de archivo como argumentos.

Puede copiarlos especificando explícitamente cp foo/.* .


1

Si lo que quiere hacer es copiar todos los archivos y directorios de un lugar a otro, puede usar el rsynccomando estándar . En el ejemplo que das arriba:

mkdir foo && touch foo/.test
rsync -a foo/ .

copiará recursivamente todo el contenido de foo, incluidos los archivos ocultos y los directorios ocultos, en el directorio actual. La barra diagonal final al final de foo/es importante para rsync; con él solo foose copia el contenido de , sin rsync también se copiará foo. Por ejemplo:-

mkdir src && mkdir dest && touch src/.test
rsync -a src  dest    // copies 'src' contents to 'dest/src'
rsync -a src/ dest    // copies 'src' contents to 'dest' 

Hay muchas otras opciones disponibles para ajustar rsync, incluida la copia entre máquinas.


1

La respuesta zsh de Stéphane Chazelas es correcta para una sola expresión con un globo. Sin embargo, si desea establecerlo para todas las expresiones de forma predeterminada, puede usar

setopt GLOB_DOTS

Ponlo en tu ~/.zshrcpara hacerlo permanente.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.