¿Cómo se mueven todos los archivos (incluidos los ocultos) de un directorio a otro?

135

¿Cómo muevo todos los archivos de un directorio (incluidos los ocultos) a otro directorio?

Por ejemplo, si tengo una carpeta "Foo" con los archivos ".hidden" y "notHidden" dentro, ¿cómo muevo ambos archivos a un directorio llamado "Bar"? Lo siguiente no funciona, ya que el archivo ".hidden" permanece en "Foo".

mv Foo/* Bar/

Inténtalo tú mismo.

mkdir Foo
mkdir Bar
touch Foo/.hidden
touch Foo/notHidden
mv Foo/* Bar/
Cory Klein
fuente
Bah, sabía que debería haber actualizado las respuestas antes de escribir las mías. Muy útil enlace.
Steven D
Lamentablemente, esta pregunta terminó aquí porque dije en SO que debería moverse aquí o SU, así que, por supuesto, se mudó aquí cuando ya había un duplicado en SU ​​:)
Michael Mrozek
Personalmente, creo que las preguntas y respuestas específicas de * nix deberían estar fuera de tema en SU. Con las reglas actuales, terminamos con toneladas de colisiones de contenido entre los dos, como esta pregunta.
Cory Klein

Respuestas:

154

Zsh

mv Foo/*(DN) Bar/

o

setopt -s glob_dots
mv Foo/*(N) Bar/

(Omita (N)si sabe que el directorio no está vacío).

Golpetazo

shopt -s dotglob nullglob
mv Foo/* Bar/

Ksh93

Si sabe que el directorio no está vacío:

FIGNORE='.?(.)'
mv Foo/* Bar/

Estándar (POSIX) sh

for x in Foo/* Foo/.[!.]* Foo/..?*; do
  if [ -e "$x" ]; then mv -- "$x" Bar/; fi
done

Si está dispuesto a permitir que el mvcomando devuelva un estado de error a pesar de que tuvo éxito, es mucho más simple:

mv Foo/* Foo/.[!.]* Foo/..?* Bar/

GNU find y GNU mv

find Foo/ -mindepth 1 -maxdepth 1 -exec mv -t Bar/ -- {} +

Hallazgo estándar

Si no le importa cambiar al directorio de origen:

cd Foo/ &&
find . -name . -o -exec sh -c 'mv -- "$@" "$0"' ../Bar/ {} + -type d -prune

Aquí hay más detalles sobre cómo controlar si los archivos de puntos coinciden en bash, ksh93 y zsh.

Golpetazo

Establece la dotglobopción .

$ echo *
none zero
$ shopt -s dotglob
$ echo *
..two .one none zero

También está la GLOBIGNOREvariable más flexible , que puede establecer en una lista de patrones comodín separados por dos puntos para ignorar. Si no está establecido (la configuración predeterminada), el shell se comporta como si el valor estuviera vacío si dotglobestá establecido, y como si el valor fuera .*si la opción no está establecida. Consulte Expansión del nombre de archivo en el manual. Los directorios omnipresentes .y ..siempre se omiten, a menos que .el patrón coincida explícitamente.

$ GLOBIGNORE='n*'
$ echo *
..two .one zero
$ echo .*
..two .one
$ unset GLOBIGNORE
$ echo .*
. .. ..two .one
$ GLOBIGNORE=.:..
$ echo .*
..two .one

Ksh93

Establece la FIGNOREvariable . Si no está establecido (la configuración predeterminada), el shell se comporta como si el valor fuera .*. Para ignorar .y .., deben coincidir explícitamente (el manual en ksh 93s + 2008-01-31 establece eso .y ..siempre se ignora, pero esto no describe correctamente el comportamiento real).

$ echo *
none zero
$ FIGNORE='@(.|..)'
$ echo *
..two .one none zero
$ FIGNORE='n*'
$ echo *
. .. ..two .one zero

Puede incluir archivos de puntos en un patrón uniéndolos explícitamente.

$ unset FIGNORE
$ echo @(*|.[^.]*|..?*)
..two .one none zero

Para que la expansión salga vacía si el directorio está vacío, use la Nopción de coincidencia de patrones: ~(N)@(*|.[^.]*|..?*)o ~(N:*|.[^.]*|..?*).

Zsh

Establece la dot_globopción .

% echo *
none zero
% setopt dot_glob
% echo *
..two .one none zero

.y ..nunca coinciden, incluso si el patrón coincide .explícitamente con el inicio.

% echo .*
..two .one

Puede incluir archivos de puntos en un patrón específico con el D calificador global .

% echo *(D)
..two .one none zero

Añadir el Ncalificativo pegote para que la expansión salido vacía en un directorio vacío: *(DN).


Nota: es posible obtener resultados expansión de nombre de archivo en diferentes órdenes (por ejemplo, noneseguido por .oneseguido por ..two) en base a la configuración de los LC_COLLATE, LC_ALLy LANGlas variables.

Gilles
fuente
1
¿Por qué nullglob? Tendría más sentido abortar el mvcomando (como fish, csh / tcsh, zsh (sin (N)) do o bash con failglob) que ejecutar un mv /Bar/comando que tiene poco sentido.
Stéphane Chazelas
1
Diría que la descripción de GLOBIGNORE es inexacta y engañosa. Establecer GLOBIGNORE en un valor no vacío activa dotglob y lo hace .y ..nunca coincide (como en otros shells sensibles como zsh, fish, pdksh y derivados) incluso si desactiva dotglob nuevamente. ( GLOBIGNORE=:; shopt -u dotglob; echo .*no saldrá .y ..). establecer GLOBIGNORE a .:..o .o :tener el mismo efecto.
Stéphane Chazelas
ksh93siempre ignorando .y ..parece haberse roto entre ksh93k+(donde funcionó) y ksh93m(donde ya no funciona). Tenga en cuenta que es malo ya que ksh93tomará el valor de FIGNORE del entorno, por lo que, FIGNORE='!(..)'por ejemplo , una variable de entorno puede crear estragos.
Stéphane Chazelas
24
#!/bin/bash

shopt -s dotglob
mv Foo/* Bar/

De man bash

dotglob Si está configurado, bash incluye nombres de archivo que comienzan con un '.' en los resultados de la expansión del nombre de ruta.

SiegeX
fuente
Con la advertencia de que este comando devuelve un código de error si el directorio estaba vacío (a pesar de que el comando realmente se realizó según lo previsto).
Gilles
1
@Gilles, el error será mvquejarse de que ese archivo llamado Foo/*no existe. Curiosamente, si Foose puede buscar, pero no se puede leer, y hay un archivo llamado *allí, no obtendrá ningún error, ese archivo se moverá, pero no los otros en el directorio. bashtiene una failglobopción para que se comporte más como zsh, fishy csh/ tcshy anule el comando con un error cuando un globo no puede expandirse en lugar de ese comportamiento falso de dejar el globo como está.
Stéphane Chazelas
8

Una manera simple de hacer esto bashes

mv {Foo/*,Foo/.*} Bar/

Pero esto también moverá directorios.

Si desea mover todos los archivos, incluidos los ocultos, pero no desea mover ningún directorio, puede usar un bucle for y probar.

for i in $(ls -d {Foo/*,Foo/.*});do test -f $i && mv -v $i Bar/; done;

Mes Boris
fuente
4

Una forma es usar find:

find Foo/ -type f -exec mv -t Bar/ {} \+

El -type frestringe el comando de búsqueda para buscar archivos. Debe investigar el -type, -maxdepthy -mindepthopciones de findpersonalizar su comando para dar cuenta de los subdirectorios. Find tiene una página de manual larga pero muy útil .

Steven D
fuente
3
Eso solo mueve los archivos normales Foo/, no subdirectorios y otros archivos.
Gilles
2

Prueba el comando copiar cp:

$ cp -r myfolder/* destinationfolder

cp -r significa copia recursiva, por lo que se copiarán todas las carpetas y archivos.

Puede usar el comando rmeliminar para eliminar una carpeta:

$ rm -r myfolder

Ver más: mover todos los archivos de un directorio a otro .

ucefkh
fuente
2
No es lo mejor cuando mueves muchos archivos grandes, pero supongo que funcionaría.
Cory Klein
¿Tal vez si usas un punto en lugar de la estrella?
Vincent
1

Rsync es otra opción:

rsync -axvP --remove-source-files sourcedirectory/ targetdirectory

Esto funciona porque en rsync la barra inclinada final importa, se sourcedirectory/refiere al contenido del directorio, mientras que sourcedirectoryse referiría al directorio en sí.

La desventaja de este método es que rsync solo limpiará los archivos después del movimiento, no el directorio. Entonces te quedas con un árbol de directorio de fuentes vacío. Para soluciones alternativas para eso, vea:

¿Mover archivos y eliminar directorios con rsync?

Entonces, aunque esto puede no ser óptimo para las operaciones de movimiento, puede ser extremadamente útil para las operaciones de copia.

Grumbel
fuente
1

Respuesta por bash / fish

Aquí hay una manera de hacerlo usando comodines:

.[!.]* ..?*coincidirá con todos los archivos ocultos excepto .y..

.[!.]* ..?* *coincidirá con todos los archivos (ocultos o no) excepto .y..

Y para responder el ejemplo particular de esta pregunta que necesita cd foo && mv .[!.]* ..?* * ../bar

Explicación

.[!.]*coincide con los nombres de archivo que comienzan con un punto, seguido de cualquier carácter, excepto el punto seguido opcionalmente por cualquier cadena. Esto está lo suficientemente cerca pero pierde archivos que comienzan con dos puntos como ..foo. Para incluir dichos archivos, agregamos los ..?*que coinciden con los nombres de los archivos que comienzan con dos puntos, seguidos de cualquier carácter, opcionalmente seguido de cualquier cadena.

Prueba

Puede probar estos comodines con los siguientes comandos. Los he probado con éxito en bash y fish. Fallan bajo sh, zsh, xonsh.

mkdir temp
cd temp
touch  a  .b  .bc  ..c  ..cd  ...d  ...de
ls .[!.]* ..?*
# you get this output:
          .b  .bc  ..c  ..cd  ...d  ...de
# cleanup
cd ..
rm -rf temp
ndemou
fuente
0

También es posible que pueda encontrar y grep con comillas inversas para seleccionar archivos para el comando mover. Pasarlos a mv.

Es decir, para archivos ocultos

find Foo -maxdepth 1 | egrep '^Foo/[.]' # Output: .hidden

Entonces

mv `find Foo -maxdepth 1 | egrep '^Foo/[.]'` Bar # mv Foo/.hidden Bar

Mueve solo los archivos ocultos seleccionados a Bar:

mv `find Foo -maxdepth 1 | egrep '^Foo/.'` Bar # mv Foo/.hidden Foo/notHidden Bar

Mueve todos los archivos de Foo a Bar desde el '.' en el comando egrep actúa como un comodín sin los corchetes.

El ^personaje asegura que la partida comience desde el principio de la línea.

Algunos detalles de la egrepcoincidencia de patrones se pueden encontrar aquí .

El uso de maxdepth 1paradas encuentra desde entrar en subdirectorios.

usuario3192145
fuente
0

Inspirado en esta respuesta :

Sin copiar los archivos ...

rsync -ax --link-dest=../Foo/ Foo/ Bar

Advertencias:

  • --link-destla ruta debe ser absoluta o relativa al DESTINO ( Bar en el ejemplo)

  • Debe colocar /después de SOURCE ( Foo/en el ejemplo), de lo contrario, copiará la carpeta SOURCE en lugar del contenido de la misma.

palindrom
fuente
0

Creo que esto funciona bien para bash y no hay necesidad de cambiar las opciones de shell

mv sourcedir/{*,.[^.]*} destdir/

EDITAR:

Entonces, como dijo G-man, mi respuesta original no es compatible con posix y es más o menos lo mismo que la respuesta de ndemou anterior con un cambio, que es usar la expansión de llaves para crear listas de cadenas que luego se actúan. Esto solo significa que no necesita cdingresar al directorio de origen. Realmente no es un cambio tan grande, pero es diferente.

ejemplo: supongamos que ya tiene el siguiente diseño.

 $ tree -a
.
├── destdir
└── sourcedir
    ├── ..d1
    ├── ..d2
    ├── ..double
    ├── file-1
    ├── file-2
    ├── .hidden-1
    ├── .hidden-2
    ├── ...t1
    └── ...t2

La pregunta original solo mencionaba archivos ocultos con un solo punto, pero digamos que hay algunos con dos o más puntos al comienzo del nombre. Simplemente puede agregar una expresión adicional en las llaves. Entonces podemos ejecutar

mv sourcedir/{*,.[!.]*,..?*} destdir/

Esto se expande a lo siguiente:

mv sourcedir/file-1 sourcedir/file-2 sourcedir/.hidden-1 sourcedir/.hidden-2 sourcedir/..d1 sourcedir/..d2 sourcedir/..double sourcedir/...t1 sourcedir/...t2 destdir/

Ahora debería ver todos los archivos ubicados en destdir :

 $ tree -a
.
├── destdir
   ├── ..d1
   ├── ..d2
   ├── ..double
   ├── file-1
   ├── file-2
   ├── .hidden-1
   ├── .hidden-2
   ├── ...t1
   └── ...t2
└── sourcedir

Puedes hacer algunas cosas geniales con llaves en bash con más adiciones en 4.x. Echa un vistazo a bash-hackers para obtener algunos ejemplos ingeniosos.

cmndr sp0ck
fuente
1
Básicamente, esto duplica la respuesta de ndemou, excepto que agregaste llaves (sin explicarlas). Pero (1) su respuesta no coincide con los archivos cuyos nombres comienzan .., y (2) para cumplir con POSIX , debe usar en !lugar de ^; es decir,  {*,.[!.]*}.
G-Man
@ G-Man, perdón por eso. Así que tienes razón y es malo que no haya visto la respuesta de ndemou. Son más o menos lo mismo. 1. Gracias por señalar que mi versión no es compatible con Posix. 2. Estoy usando la expansión de llaves para crear listas de cadenas que el shell usará para realizar una acción. Esto también significa que no necesito cdingresar al directorio de origen para actuar sobre los archivos o escribir las mismas rutas de archivo una y otra vez para expresar las rutas a todos los archivos. Actualizaré el ejemplo en breve para darles a los lectores una mejor idea de lo que estoy hablando.
cmndr sp0ck
0

Para distribuciones mínimas de Linux, lo siguiente debería funcionar. Primero, realice un movimiento básico de todos (que pierde los archivos ocultos). A continuación, mueva todos los archivos ocultos (incluyendo el .y ..que será no realmente se mueva).

mv /sourceDir/* /destinationDir 2> /dev/null
mv /sourceDir/.* /destinationDir 2> /dev/null

Notas: Si no hay contenido visible, el primer comando generará un mensaje de error. El segundo comando siempre producirá un error diciendo que no puede moverse .y ... Como tal, simplemente canalice los errores /dev/null(como se muestra).

Si necesita esto como una línea, simplemente combínelos con un punto y coma:

mv /sourceDir/* /destinationDir 2> /dev/null; mv /sourceDir/.* /destinationDir 2> /dev/null
BuvinJ
fuente