¿Cómo puedo obtener mv (o el comodín *) para mover archivos ocultos?

134

Estoy migrando mi directorio de inicio de un sistema antiguo a uno nuevo, y el tarball que hice contiene todo, incluidos archivos ocultos como .bashrc. Sin embargo, cuando muevo el contenido del tarball desempaquetado (que están en / tmp) a mi nuevo directorio de inicio, los archivos ocultos no se copian ( mv /tmp/home/rcook/* /home/rcook/). ¿Cómo puedo hacer que mv los mueva?

En realidad, creo que el problema no es con mv, sino con el problema de bash. Si hago esto:

mkdir a
mkdir b
touch a/.foo
touch a/bar
mv a/* b/
ls -a a/ b/

Veo esto:

a/:
.  ..  .foo

b/:
.  ..  bar

a/.foono se movió. Entonces, ¿cómo puedo obtener el comodín * para encontrar archivos ocultos?

Sí, supongo que podría descomprimir el tarball directamente en mi directorio de inicio, pero el tarball se descomprime home/rcook/...y quiero asegurarme de sobrescribir el nuevo .bashrc, etc.con las versiones antiguas y personalizadas, y saber cómo encontrar y mover archivos ocultos. Es una habilidad que vale la pena. Sugerencias?


Algunas respuestas sugieren hacer algo como mv src/.* dest/. Sin embargo, intenté esto en mis directorios de prueba y obtuve errores. Empezando con:

rcook$ ls -a a/ b/
a/:
.  ..  bar  .foo

b/:
.  ..
rcook$ mv a/.* b/
mv: cannot move 'a/.' to 'b/.': Device or resource busy
mv: cannot remove 'a/..': Is a directory
rcook$ ls -a a/ b/
a/:
.  ..  bar

b/:
.  ..  .foo

¿Qué estoy haciendo mal?

Randall Cook
fuente

Respuestas:

147

Puedes hacerlo :

shopt -s dotglob
mv /tmp/home/rcook/* /home/rcook/

Puedes poner

shopt -s dotglob

en su ~/.bashrcsi desea que sea el predeterminado.

Ver http://mywiki.wooledge.org/glob


Otro enfoque para copiar los archivos de puntos:

mv /tmp/home/rcook/.[!.]* /home/rcook/

No utilice el patrón ..*como coincide ..(puntero al directorio principal). Si hay archivos cuyo nombre comienza con dos puntos ( ..something), también use el patrón ..?*.

Gilles Quenot
fuente
Por favor revise las adiciones que puse al final de mi pregunta. Gracias.
Randall Cook
1
Nada está mal, .y ..son directorios especiales: respectivamente, el directorio actual y el directorio principal . Es solo una advertencia. Mejor shopt -s dotglobsolución de uso
Gilles Quenot
Terminé haciendo dos movimientos: mv home/rcook/* /home/rcook/seguido por mv home/rcook/.* /home/rcook/. Esto funcionó, aunque desearía haber seguido el enlace y leer sobre el modo dotglob primero. Me hubiera ahorrado un paso. +1
Randall Cook
Entonces, ¿el segundo enfoque requiere el uso de rutas absolutas?
franzlorenzon
3
Si está usando zsh, puede usar el Dcalificador global o la GLOB_DOTSopción de shell .
mgalgs
43

En sus adiciones, obtuvo errores pero el código aún funcionó. La única cosa que añadir es que usted haya indicado solamente para copiar los archivos punto. Tratar:

mv src/* src/.* dst/

Aún obtendrá los errores para el. y ... entradas, lo cual está bien. Pero el movimiento debería tener éxito.

~/scratch [andrew] $ mv from/* from/.* to/
mv: cannot move from/.’ to to/.’: Device or resource busy
mv: cannot remove from/..’: Is a directory
~/scratch [andrew] $ ls -a from/ to/
from/:
.  ..

to/:
.  ..  test  .test
Andrew Schwartz
fuente
1
Buenos puntos, @AndrewSchwartz. También me gusta este enfoque. Creo que merece más reconocimiento.
Randall Cook
Me gusta la respuesta de @Drake Clarris un poco más, porque estoy ejecutando en Amazon AWS CodeBuild y el código de retorno distinto de cero realmente hizo que mi compilación se detuviera. Sin .hiddenembargo, terminé moviendo el único archivo que tenía explícitamente para resolver mi problema.
Hola
Si el código de salida distinto de cero es un problema, puede suprimirlo, por ejemplo, agregando || :( ||significa ejecutar lo siguiente en falso / error, :es un comando noop). Pero eso también suprimiría errores legítimos, por ejemplo, la carpeta de destino no existe. No puedo encontrar una manera más elegante usando mvpara excluir las entradas .y ... Butt big plus para mí sobre cp no es escribir nuevos archivos en el disco.
Andrew Schwartz
10

Si está ls -len un directorio, verá .y ..entre los archivos enumerados. Entonces, creo que mv .* /desttoma en cuenta esos indicadores. Tratar:

mv /tmp/home/rcook/{*,.[^.]*,..?*} /home/rcook/

esto ignorará los punteros de directorio actuales y principales.

Obtendrá un error si cualquiera de los tres patrones *, [^.]*o ..?*partidos ningún archivo, por lo que sólo debe incluir los que coinciden.

Azamat
fuente
Agradable. Una respuesta similar para este estilo de englobamiento está aquí: superuser.com/a/784046/144977 . Gracias por publicar esto.
phyatt
7

Dos posibles soluciones en las que puedo pensar. El primero es usar cp en su lugar con su opción recursiva, copiando el directorio actual al destino.

cp -Rp . /desired/directory

entonces puede eliminar los archivos de origen en el directorio actual

Alternativamente, si sabe que los archivos tienen nombres correctos (sin espacios, comodines, caracteres no imprimibles), puede hacer algo como esto

mv $(ls -A) /desired/directory
Drake Clarris
fuente
44
Copiar-luego-eliminar es muy diferente de mover si la fuente y el destino están en el mismo sistema de archivos. Al menos incluya la opción -pde preservar metadatos. Usar lsdebería ser el último recurso, y aquí hay formas mejores y más simples.
Gilles
2

Realmente no hay tal cosa como archivos "ocultos" en Linux. Los archivos que comienzan con un punto simplemente están ocultos de las listas de archivos de forma predeterminada.

Para copiar los archivos, incluso con un pegote, es necesario anteponer el archivo con .como mv -u .* fooy luego .foose appearn como foo/.foocuando se mueven.

La opción -u solo moverá los archivos cuando el origen sea más nuevo o falte el destino. O bien, puede ignorar los errores sobre el movimiento .y, ..dado que son archivos especiales y no se pueden mover, pero .*el shell lo atrapa en el globo.

dobey
fuente
Por favor revise las adiciones que puse al final de mi pregunta. Gracias.
Randall Cook
0

Entonces tenemos:

a
|-- .foo
`-- bar

y:

b

Me tomé un tiempo enorme para encontrar una mejor solución que todas las respuestas aquí.

Luego tomé 30 segundos para este comando:

$ mv --help

Entonces encontré mi amor:

$ mv a/ b/ -T

Nota: Ni siquiera entiendo el argumento -T. Simplemente hizo lo que necesitaba. Aquí dice:

-T, --no-target-directory trata DEST como un archivo normal

user433901
fuente
1
Si omite las barras, no debería necesitarlas -T. De cualquier manera, esto esencialmente le dice a mv que mueva el directorio en sí, en lugar de mover todos los archivos desde su interior.
thomasrutter
@thomasrutter, ¿no es mover el directorio en sí lo mismo que renombrarlo?
Randall Cook
3
Sí, si el destino principal sigue siendo el mismo, esencialmente solo se cambia el nombre. Independientemente de cómo se refiera, probablemente no ayude a responder la pregunta original, que era sobre mover los archivos dentro del directorio a una ubicación determinada.
thomasrutter
0

En mi caso, simplemente estaba intentando mvun único archivo oculto y esta fue la solución:

FILE=.myHiddenFile
mv "$FILE" dest/

Explicación

Al principio estaba intentando:

mv .myHiddenFile dest/

Pero siguió produciendo el error:

mv: cannot stat '.myHiddenFile': No such file or directory

A pesar de ls -alque mostró que el archivo y dest/existía.

La razón parece ser porque el shell estaba interpretando el "." en el nombre del archivo, por lo que al moverlo a una variable evita la interpretación. Probablemente hay otras formas de resolver esto, pero esto fue suficiente para nosotros.

Isaias
fuente
-1

Si desea copiar archivos, incluidos los archivos ocultos, en el directorio actual en el que se encuentra.

cp -Rp source-directory/. .
Almiar
fuente
1
Esto es muy similar a la respuesta de Drake Clarris de 2013. ¿Tienes algo más que agregar?
Randall Cook