¿Cómo copiar archivos y subdirectorios ocultos (comenzando con un punto) en Linux?

10

¿Cómo copiar archivos ocultos y subdirectorios ocultos (los que comienzan con un punto) en la carpeta A a la carpeta B? Por ejemplo si tengo esta estructura:

A/a
A/b
A/.a
A/.b/
A/.b/somefile
A/.b/.c

Me gustaría copiar a B solo los archivos ocultos y los subdirectorios ocultos en A:

B/.a
B/.b/
B/.b/somefile
B/.b/.c

Ya probé este comando: cp A/.* Bde esta otra pregunta de superusuario . Sin embargo, no copia los subdirectorios. También lo intenté cp -r A/.* B, pero se copia, .así que termino con una copia exacta de A (incluidos los archivos normales). Cualquier ayuda es apreciada.

gaboroncancio
fuente

Respuestas:

16

Siempre y cuando solo esté buscando archivos y carpetas ocultos en el nivel de A y no desee, por ejemplo

A/b/.hidden

para ser copiado, deberías poder usar esto:

cp -r A/.[^.]* B

Básicamente significa copiar todo lo que comienza con ay .luego cualquier carácter que no sea un .que se filtra .y..

Editar: se eliminó el -p del comando cp ya que Asker no ha indicado que quiere preservar ninguna propiedad, fecha, etc.

Omnipresencia
fuente
Esto funciona para los nombres de archivo y directorio de ejemplo dados en la pregunta, pero el texto de la pregunta dice "archivos ocultos y subdirectorios ocultos (los que comienzan con un punto)", y esta respuesta no encontrará archivos y directorios cuyos nombres comiencen con dos puntos por ejemplo, ..c.
Scott
Es un caso bastante marginal, pero una preocupación legítima, no obstante. No lo había considerado. Podrías dar cuenta de eso cambiando a, .*[^.]pero luego te perderías los archivos que terminan en a .. Creo que, de hecho, necesitaría un globbing extendido para realmente explicar todos los casos.
Omnipresencia
4

El problema con A/.*es que existe el directorio .en el Aque también coincide con el patrón.

Puede activar patrones de glob extendido y usar lo siguiente:

shopt -s extglob
cp -r A/.!(?(.)) B    

Coincide con los archivos cuyo nombre comienza con un punto y cuyo segundo carácter no es ni un punto ni nada (? (.) No coincide con nada o un punto,! (...) lo niega, es decir! (? (.)) Coincide con todo lo demás que nada o un punto).

choroba
fuente
+1 para una respuesta correcta. Tenga en cuenta que .!(@(|.))es (AFAICT) equivalente al anterior, (IMNSHO) un poco más claro y solo un carácter más.
Scott
3

Para casos como este recomendaría usar en findlugar de cpesto:

find A/ -type f -maxdepth 1 -name '.*' -exec cp -p {} B/ \;

La sintaxis básica se desglosa así:

  • find A/ -type f: findelementos en el directorio A/cuyo tipo es un archivo (en lugar de un directorio) ...
  • -maxdepth 1 -name '.*': Para esto para un maxdepthde 1 directorios y cuyo namecomienza con ..
  • -exec cp -p {} B/ \;: Y una vez que se encuentran estos archivos, execel cpcomando con una -pbandera para preservar fechas / horas desde el origen ( {}) hasta el destino de B/.

Me gusta usar maxdepthpara agregar una capa de control, así que no estoy copiando accidentalmente un sistema de archivos completo. Pero siéntase libre de eliminar eso.

JakeGould
fuente
0
 for item in `find A -type d | grep -E "\."` ; do cp -r $item B ; done
  • find A -type d proporciona una lista recursiva dentro de A con solo directorios
  • grep -E "\." filtra los directorios con un punto (es decir, directorios ocultos)
  • la opción -E era necesaria aquí porque sin ella también significa "directorio actual"
  • la barra invertida es evitar el significado, bajo regexp, de "cualquier personaje"
  • cp -r copiar recursivamente

Creé la estructura de archivos y carpetas para A y ejecuté el comando en Git Bash (no estoy con un Linux en este momento) y funcionó.

malarres
fuente
Esto se rompe si los archivos tienen espacios en blanco o caracteres especiales en su nombre o ruta.
slhck
Gracias por notar :) En realidad me limité al "caso de prueba" de @gaboroncancio. Si usted me puede dar otra batería de pruebas que pueden tratar de mejorar eso (por supuesto, si usted quiere, mejorar por sí mismo, ya sea editando esta respuesta o la creación de una nueva respuesta)
malarres
Simplemente podría poner los archivos de puntos en una carpeta llamada A B, y luego actuaría inesperadamente porque se expandiría a cp -r A B/.dotfile B. El consejo general es no analizar findo lsgenerar en absoluto. Si usa find, también debe usar sus propias opciones para filtrar en lugar de grep, y si canaliza la findsalida en otro lugar, use -print0o llame directamente al comando que desee. Ver el find manual .
slhck
Incluso de manera más general, cuando se trabaja con archivos, es más seguro usar globs de shell como se explica en otras respuestas (aunque a menudo requieren extglobser configurados).
slhck
Gracias por el enlace. Dejemos el findanálisis entonces.
malarres
0

Como alternativa, puede usar este otro comando si el segundo carácter es alfanumérico ( fuente ):

cp -r A/.[a-zA-Z0-9]* B
gaboroncancio
fuente
Esto funciona para los nombres de archivo y directorio de ejemplo dados en la pregunta, pero el texto de la pregunta dice "archivos ocultos y subdirectorios ocultos (los que comienzan con un punto)", y esta respuesta no encontrará archivos y directorios cuyos nombres comiencen con un punto y un caracter especial; por ejemplo, .@fooo ..c.
Scott
Es por eso que señalo que funciona si el segundo carácter es alfanumérico. ;)
gaboroncancio