Cómo mover todos los archivos, incluidos los archivos ocultos, al directorio principal a través de *

113

Debe ser una pregunta popular pero no pude encontrar una respuesta.

Cómo mover todos los archivos a través de * incluidos los archivos ocultos al directorio principal como este:

mv /path/subfolder/* /path/

Esto moverá todos los archivos al directorio principal como se esperaba, pero no moverá los archivos ocultos. ¿Como hacer eso?

TroodoN-Mike
fuente
1
esta pregunta tiene un duplicado en SU , con una respuesta aún más correcta (aunque no la aceptada): cp -r /path/to/source/. /destination
Florian

Respuestas:

202

Puede encontrar un conjunto completo de soluciones al respecto en la respuesta de UNIX y Linux a ¿Cómo se mueven todos los archivos (incluidos los ocultos) de un directorio a otro? . Muestra soluciones en Bash, zsh, ksh93, estándar (POSIX) sh, etc.


Puede usar estos dos comandos juntos:

mv /path/subfolder/* /path/   # your current approach
mv /path/subfolder/.* /path/  # this one for hidden files

O todos juntos ( gracias pfnuesel ):

mv /path/subfolder/{.,}* /path/

Que se expande a:

mv /path/subfolder/* /path/subfolder/.* /path/

(ejemplo: se echo a{.,}bexpande a a.b ab)

Tenga en cuenta que esto mostrará un par de advertencias:

mv: cannot move ‘/path/subfolder/.’ to /path/.’: Device or resource busy
mv: cannot remove /path/subfolder/..’: Is a directory

Simplemente ignórelos: esto sucede porque /path/subfolder/{.,}*también se expande a /path/subfolder/.y /path/subfolder/.., que son el directorio y el directorio principal (consulte ¿Qué significan "." Y ".." cuando están en una carpeta? ).


Si solo desea copiar, puede usar un simple:

cp -r /path/subfolder/. /path/
#                     ^
#                     note the dot!

Esto copiará todos los archivos, tanto los normales como los ocultos, ya que se /path/subfolder/.expande a "todo lo de este directorio" (Fuente: ¿Cómo copiar con cp para incluir archivos ocultos y directorios ocultos y su contenido? )

fedorqui 'Así que deja de hacer daño'
fuente
2
Las llaves son solo un atajo mv /path/subfolder/* /path/subfolder/.* /path/, no es estrictamente necesario para combinar los dos comandos en uno.
chepner
7
Recibo el siguiente error:mv: overwrite `/path/.'? y mv: cannot move `/path/subfolder/.' to `/path/.': Device or resource busy mv: overwrite `/path/..'? y mv: cannot move `/path/subfolder/..' to `/path/..': Device or resource busy
Dejan
@Dejan Solo ignóralo. .denota directorio actual y ..denota updirectorio. Debes haber notado que todos los demás archivos se mueven.
Debiprasad
Vale la pena mencionar que el atajo de llaves no funcionará para todos los shells, pero el comando @chepner creo que sí
Jesús Carrera
7
"Simplemente ignore la advertencia" puede no ser siempre una buena idea. En este momento tengo un problema con un script en el que necesito detener la ejecución si falla algún paso, ya que esta solución siempre causa un error, mata mi script. Necesito una forma de determinar si el comando mv falló o no ...
MarioVilas
29

Creo que este es el más elegante, ya que tampoco intenta moverse ..:

mv /source/path/{.[!.],}* /destination/path
Vanderstaaij
fuente
1
sí, lo noté dando esos mensajes de error también, buen hallazgo.
Joseph Astrahan
Creo que esta es una muy buena solución, pero es un poco difícil recordar ese patrón
Dylan B
esto perdería archivos como ..anythingo ...anythingetc. - stackoverflow.com/a/31438355/2351568 contiene la expresión regular correcta para este problema. || ¡Pero de todos modos usar shopt -s dotglobsigue siendo la mejor solución!
DJCrashdummy
@DylanB no lo memorices. recuerde que coincide con lo que esté en los corchetes, separados por comas. {a,b}*encontraría todos los archivos que empiecen con aob, como "anatomía" y "bulldozer". La segunda coincidencia es solo una coincidencia vacía, equivalente a *, y la primera coincidencia es equivalente a .[!.], donde el grupo [!.]significa un grupo que NO comienza con a .. Esto significa .*pero no ..*.
mazunki
28

Esto moverá todos los archivos al directorio principal como se esperaba, pero no moverá los archivos ocultos. ¿Como hacer eso?

Podrías encender dotglob:

shopt -s dotglob               # This would cause mv below to match hidden files
mv /path/subfolder/* /path/

Para apagar dotglob, deberías decir:

shopt -u dotglob
devnull
fuente
Muy útil. Quería obtener más información, pero shopt está incorporado, por lo man shoptque no funciona y help shoptes muy breve. Pero puedes hacerlo bashman () { man bash | less -p "^ $1 "; }y luego bashman shoptleer todo sobre él directamente. (Es posible que tenga que presionar n para saltar al comando si hay líneas que comienzan con shopt, como descubrí).
Nick Rice
2
esto también afectará a todos los demás comandos como ls... por lo tanto, no es realmente lo que querrías, probablemente
phil294
5

Una solución alternativa más sencilla es utilizar la rsyncutilidad:

sudo rsync -vuar --delete-after --dry-run path/subfolder/ path/

Nota: El comando anterior mostrará lo que se va a cambiar. Para ejecutar los cambios reales, elimine--dry-run .

La ventaja es que la carpeta original ( subfolder) se eliminaría así como parte del comando, y al usar mvejemplos aquí, aún necesita limpiar sus carpetas, sin mencionar el dolor de cabeza adicional para cubrir archivos ocultos y no ocultos en una sola. patrón.

Además, rsyncbrinda soporte para copiar / mover archivos entre controles remotos y aseguraría que los archivos se copien exactamente como estaban originalmente ( -a).

El -uparámetro utilizado omitiría los archivos más nuevos existentes, volvería -ra los directorios y -vaumentaría la verbosidad.

Kenorb
fuente
¡La mejor solución! En mi caso, acabo de eliminar el parámetro -u, porque no me gustaría actualizar la carpeta raíz. Gracias
Thales Ceolin
Este es uno de esos comandos en los que, si no tienes cuidado, puedes estropear las cosas en Linux de forma permanente. Actualice su respuesta para incluir sudo antes del comando rsync; de lo contrario, los usuarios pueden obtener fácilmente el Permiso denegado para mkdir, pero las eliminaciones de archivos seguirán adelante, por lo que el comando rsync eliminará todo el directorio que desea mover y no hará nada más . Perderá todo su directorio. Una vez que agregue sudo a su respuesta, esta probablemente debería ser la respuesta aceptada. Por lo tanto, el comando debería ser: sudo rsync -vuar --delete-after path / subfolder / path /
Blue Water
@JohnnyB Disculpe las molestias. Agregué sudoy --dry-run, para que la gente pueda probar los cambios antes de ejecutar el comando real para evitar posibles problemas.
Kenorb
Oh, no me di cuenta de que había una opción de ejecución en seco. Buena adición. No hay necesidad de disculparse. Esto es excelente.
Blue Water
3

Permítanme presentarles a mi amigo "dotglob". Se activa y desactiva si "*" incluye archivos ocultos o no.

$ mkdir test
$ cd test
$ touch a b c .hidden .hi .den
$ ls -a
. ..  .den  .hi .hidden a b c

$ shopt -u dotglob
$ ls *
a b c
$ for i in * ; do echo I found: $i ; done
I found: a
I found: b
I found: c

$ shopt -s dotglob
$ ls *
.den  .hi .hidden a b c
$ for i in * ; do echo I found: $i ; done
I found: .den
I found: .hi
I found: .hidden
I found: a
I found: b
I found: c

El valor predeterminado es "desactivado".

$ shopt dotglob
dotglob         off

Es mejor volver a encenderlo cuando haya terminado, de lo contrario confundirá las cosas que asumen que estará apagado.

TomOnTime
fuente
3

Al usar el findcomando junto con el mvcomando, puede evitar que el mvcomando intente mover directorios (por ejemplo, ..y .) y subdirectorios. Aquí tienes una opción:

find /path/subfolder -maxdepth 1 -type f -name '*' -exec mv -n {} /path \;

Hay problemas con algunas de las otras respuestas proporcionadas. Por ejemplo, cada uno de los siguientes intentará mover subdirectorios de la ruta de origen:

1) mv /path/subfolder/* /path/ ; mv /path/subfolder/.* /path/
2) mv /path/subfolder/{.,}* /path/ 
3) mv /source/path/{.[!.],}* /destination/path

Además, 2) incluye el. y .. archivos y 3) pierde archivos como ..foobar, ... barfoo, etc.

Podría usar mv /source/path/{.[!.],..?,}* /destination/path,, que incluiría los archivos omitidos por 3), pero aún así intentaría mover subdirectorios. Usar el findcomando con el mvcomando como describo anteriormente elimina todos estos problemas.

teancum144
fuente
2

Mi solución para este problema cuando tengo que copiar todos los archivos (incluidos los .archivos) en un directorio de destino que conserva los permisos es: (sobrescribir si ya existe)

yes | cp -rvp /source/directory /destination/directory/

yeses para sobrescribir automáticamente archivos de destino, rrecursivo, vdetallado, pretener permisos.

Observe que la ruta de origen no termina con a/ (por lo que se copian todos los archivos / directorio y archivos.)

El directorio de destino termina/ cuando colocamos el contenido de la carpeta de origen en el destino como un todo.

Rajneesh Gadge
fuente
Si bien yeses un comando increíble para usar si desea anular los archivos de destino, no siempre se desea. Úselo solo si está seguro de que desea hacer esto. Además, ¿hay alguna diferencia entre yes | cp ...y cp -f ...?
mazunki