¿Cómo mover todos los archivos del directorio actual al directorio superior?

133

¿Cómo mover todos los archivos del directorio actual al directorio superior en Linux?

Intenté algo así mv *.*, pero no funciona.

Jens Erat
fuente
No tengo suficiente representante para volver a plantear preguntas, pero ¿puedo sugerir [linux] [mv] [cwd] [files]algo similar?
Stephan202
He vuelto a etiquetar esta pregunta por solicitud de Stephan202.
once81

Respuestas:

202

El comando que estás buscando es

mv * .[^.]* ..

o (ver más abajo para más información):

(shopt -s dotglob; mv -- * ..)

Explicación: el mvcomando mueve archivos y directorios. El último argumento para mves el destino (en este caso, el directorio un paso "arriba" en el árbol ..). Los argumentos anteriores son los archivos y directorios de origen. El asterisco ( *) es un comodín que coincide con todos los archivos que no comienzan con un punto. Los archivos que comienzan con un punto (archivos de puntos) están "ocultos". Se hacen coincidir usando el patrón .[^.]*(ver edición a continuación).

Consulte la página de manual que he vinculado para obtener más información mv.


¿Por qué en .[^.]*lugar de .*?

Como Chris Johnsen señala correctamente: el patrón .*también coincide .y ... Dado que no desea (y no puede) moverlos, es mejor usar un patrón que coincida con cualquier nombre de archivo que comience con un punto, excepto esos dos . El patrón .[^.]*hace exactamente eso: coincide con cualquier nombre de archivo (1) que comience con un punto (2) seguido de un carácter que no sea un punto (3) seguido de cero o más caracteres arbitrarios.

Como señala Paggas , también tendríamos que agregar el patrón para hacer coincidir los archivos que comienzan con dos puntos. Vea su respuesta para una solución alternativa usando ..??*find

La respuesta de Arjan menciona shoptpara evitar todos esos problemas con los archivos de puntos. Pero aún existe el problema con los archivos que comienzan con un guión. Y requiere tres comandos. Aún así, me gusta la idea. Propongo usarlo así:

(shopt -s dotglob; mv -- * ..)

Esto se ejecuta shopten una subshell (por lo tanto, no se shoptrequiere una segunda llamada ) y se usa --para que los archivos que comienzan con un guión no se interpreten como argumentos para mv.

Stephan202
fuente
77
El uso .*podría causar mv para producir advertencias / errores por no ser capaz de moverse .y ... Podrías intentarlo en su mv * .[^.]* ..lugar.
Chris Johnsen
1
@alain: de nada, ¡y bienvenido al sitio! (Si (y solo si) una de las publicaciones aquí respondió suficientemente a su pregunta, entonces puede marcarla como tal. Eso le dará al póster 15 puntos de reputación adicionales y también le dará 2 repeticiones adicionales).
Stephan202
Realmente me gusta la solución shopt que se ejecuta en una subshell :)
Paggas
2
No hay daño en la sintaxis *. *, Incluyendo ... solo es peligroso cuando se usa con chmod y chown y el indicador "recurse", es decir, chmod -R o chown -R. Y en esos casos, nunca escriba chown. * O chmod. *: Muestre el directorio superior en la ruta que está buscando y use -h (no siga los enlaces simbólicos). Pero mv ... simplemente no hace nada, así que no te preocupes por eso.
Chris
1
Los tres patrones correctos son *, .[^.]*y ..?*. El segundo tal vez .[!.]*para conchas más antiguas (POSIX). Lea también
42

Respuesta corta: uso

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

Respuesta larga:

El comando

mv * .* ..

no funcionará ya que .*puede coincidir .y ... Pero el comando

mv * .[^.]* ..

tampoco funcionará, ya .[^.]*que no coincidirá, por ejemplo ..filename,! En cambio, lo que hago es

mv * .[^.] .??* ..

que coincidirá con todo excepto .y ... *coincidirá con todo lo que no comience con un ., .[^.]coincidirá con los nombres de archivo de 2 caracteres que comienzan con un punto .., excepto , y .??*coincidirá con todos los nombres de archivo que comienzan con un punto con al menos 3 caracteres.

Mejor aún, puedes usar

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

lo que evita los trucos de feo globo mv * .[^.] .??* ..!

Paggas
fuente
1
Además, olvidé señalar la importancia de - para que el comando funcione correctamente con nombres de archivos que comienzan con un guión. He incluido, sin embargo, en mi respuesta de búsqueda. Una respuesta más completa usando globos es "mv - *. [^.]. ?? * ..".
Paggas
+1: Regresé para agregar ..?*a mi comentario, y ya lo habías hecho cargo.
Chris Johnsen
1
¿Qué puede estar mal al intentar mv ..? Simplemente no hace nada y no puede hacer nada. Hay otros comandos donde puede hacer algo (chmod y chown) pero mv y rm simplemente no hacen nada. o ..
Chris
1
Esto le da a mv: opción ilegal - t
pal4life
1
Bono, los guiones dobles le dicen mvque deje de buscar otras opciones de comando. Las llaves son un nombre de archivo resultante. El signo más dice: en lugar de ejecutar exec por resultado (es decir, por nombre de archivo), coloque tantos resultados en un solo exec como sea posible. Para completar, -t..es decir mover el destino de destino para mover todos estos archivos.
isuldor
14

Solo en aras de la integridad, uno también puede decirle al shell Bash que incluya archivos ocultos, usando shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob
Arjan
fuente
+1. Mucho más limpio. Sin embargo, creo que una pequeña mejora está en orden. Vea la actualización de mi respuesta.
Stephan202
8

El mv carece de la funcionalidad de mover archivos ocultos cuando se usa *, entonces, ¿por qué no usar copy en su lugar?

cp -rf . ..

rm -rf *

No es necesario entrar en soluciones complejas de dotglobbing y usar comandos de búsqueda

Micky Martin
fuente
Advertencia Si se está moviendo en el mismo sistema de archivos , en la mayor parte de los casos realmente no copió los archivos, sino que solo actualizó las entradas del directorio sin mover el inodo o los contenedores de archivos. Ver incluso [1 ]. Con un cpy rmen su lugar realmente estás copiando todo.
Hastur
6
rsync -a --remove-source-files . ..

rsync es una herramienta de copia de archivos extremadamente poderosa, generalmente utilizada para realizar copias de seguridad y espejos remotos incrementales eficientes.

Con el comando anterior, le estamos diciendo rsynca copiar el contenido de .dentro..

El conmutador -ahabilita la recursividad en .subdirectorios y habilita algunas otras opciones comunes.

El interruptor --remove-source-filesle dice a rsync que elimine los archivos de origen después de una copia exitosa, es decir, hace que rsync se comporte de manera similar al mvcomando.

mrucci
fuente
1
Un poco más de explicación sería bueno.
ChrisF
Claro, espero que esté más claro ahora.
mrucci
Tenga en cuenta que --remove-source-filesno eliminará los directorios (sincronizados).
Dennis
Agradable, la solución aceptada me da un -bash: /bin/mv: Argument list too longerror. Este funciona como el encanto.
userlond
2

En última instancia, el intento mv .fallará porque mv no podrá desvincular el directorio en el que se encuentra actualmente. Podría mv * ..mover los archivos en el cwd.

DaveParillo
fuente
2
mv * .??* ../.

*obtiene todos los archivos sin puntos. .??*se lleva todo. archivos de al menos tres bytes de longitud, lo que funciona para todos los legítimos. Cualquier cosa que te quede probablemente quieras rmmás que de mvtodos modos.

El ../.no ofrece ningún beneficio directo, ..pero al hacer un movimiento al directorio es un muy buen hábito, porque fallará, como lo desea, si hay algún problema con el camino. Por ejemplo, mv xyz bletchdonde crees que bletch es un directorio, puedes estar más seguro con mv xyz bletch/..

DigitalRoss
fuente
2
Puede agregar .[^.]para obtener archivos de portada como .a.
Chris Johnsen
No hay diferencia entre ../ y ../. así que no me molestaría en escribir el. Después del corte. Además, en el caso de mv y rm, no hace daño incluirlo. y ... en la lista, es decir, no hay nada aterrador o incorrecto con mv *. * / path / to / file /, como rm. o incluso -rf. no hace nada
Chris
2

Este comando minimizado funciona en la mayoría de los shells modernos:

\mv -- {,.{[^.],??}}* ..

De lo contrario, se menciona una solución portátil:

\mv -- * .[^.] .??* ..

caracteristicas:

  1. \ evita que los alias alteren mv indeseablemente.

  2. - evita que los nombres de archivo que contienen guiones iniciales (-xyz) se interpreten como argumentos de línea de comandos.

  3. . [^.] coincide con los dos nombres de archivo de caracteres que comienzan con. excepto ..

  4. . ?? * coincide con todos los demás nombres de archivo de tres caracteres o más.

Implementaciones ingenuas:

  1. A continuación se omiten los nombres de archivos UNIX ocultos, aquellos que comienzan con. (.bashrc).

    mv * ..
    
  2. Las siguientes coincidencias ... que intenta recursivamente mover todos los directorios eventualmente de regreso a / en ... del directorio de trabajo actual ($ PWD o pwd). Nunca usar.

    mv .* ..
    
dhchdhd
fuente
2

Es más correcto usar el patrón * .[!.] .??*que * .[^.] .??*ya que el primero también funcionará con shells más antiguos como ksh88:

mv -- * .[!.] .??* ..
  • -- evita problemas cuando tiene un nombre de archivo que comienza con -
  • * coincide con todos los nombres de archivo que no comienzan con un .
  • no hay nombres de archivos de un solo personaje que comiencen con un .que pueda / deba mover
  • .[!.] coincide con los dos nombres de archivo de caracteres que comienzan con un .
  • .??* coincide con los tres nombres de archivo de caracteres (o más largos) que comienzan con un .

Con ksh88, el patrón de nombre de archivo .[^.]de hecho coincidirá con los nombres de archivo ..(que siempre existe) y .^(que probablemente no existe), teniendo un efecto opuesto al deseado.

jrw32982
fuente
0

Encuentra y trabaja mucho también. Este tipo de estructura puede ser útil si desea seleccionar archivos con criterios más complicados modificando find y egrep.

find -maxdepth 1 | egrep '^./.'         # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..
usuario3192145
fuente
0

Creo que la solución más fácil para mover todos los archivos a su directorio principal. sería

mv "`ls`" ../

o, si hay archivos / directorios ocultos

utilizar:

mv "`ls -a`" ../ 2>/dev/null

Además, supongamos que desea mover el contenido de alguna carpeta a una de sus carpetas internas tony (digamos)

utilizar:

mv "`ls -a`" /tony 2>/dev/null

Nota:

"`ls -a`" 

Para mover los archivos que tienen espacios.

2>/dev/null

Es para la supresión de la advertencia / error porque ls -asería imprimir el .y ..carpeta, así y no se puede mover o copiar. Entonces, para esas carpetas, mostrará un error (si no usamos 2> / dev / null) de que no puede moverlas y el resto se moverá con bastante comodidad.

Lo mejor es evitar ls -asi no hay archivos ocultos y solo usar ls.

Prabhat Kumar Singh
fuente
¿Has probado lo que sucederá cuando corras mv $(ls -a)? Eso tocaría el directorio actual y el directorio debajo de él, porque también se ls -agenerará ...
Sami Laine
Gracias, @SamiLaine por la sugerencia que he hecho las correcciones. Pero mv ls -a ../también habría funcionado según las necesidades, sí, mostrará esos errores como mencioné anteriormente, pero aparte de eso, moverá las carpetas / archivos necesarios al directorio principal.
Prabhat Kumar Singh
Esto no funcionará para archivos con espacios.
kenorb
@kenorb necesita comillas dobles lspara poder mover archivos con espacios. He realizado los cambios necesarios. Gracias por señalarlo.
Prabhat Kumar Singh