Mover todos los archivos excepto uno

155

¿Cómo puedo mover todos los archivos excepto uno? Estoy buscando algo como:

'mv ~/Linux/Old/!Tux.png ~/Linux/New/'

donde muevo cosas viejas a carpetas nuevas, excepto Tux.png. ! -sign representa una negación. ¿Hay alguna herramienta para el trabajo?

Léo Léopold Hertz 준영
fuente

Respuestas:

142

Si usa bash y tiene extglobconfigurada la opción de shell (que suele ser el caso):

mv ~/Linux/Old/!(Tux.png) ~/Linux/New/
algo
fuente
1
Me equivoqué cuando probé el comando para muchos elementos: mv ~ / Linux / Old /! (Tux.png Tux1.png Tux2.png) ~ / Linux / New / Vacía todo el directorio Old. ¿Qué está mal?
Léo Léopold Hertz 준영
55
@UnixBasics, prueba: ~ / Linux / Old /! (Tux.png | Tux1.png | Tux2.png)
Juliano
@Juliano ¡Muy buen comando! ¿Hay más operaciones matemáticas como OR y XOR? Supongo que una tubería es para AND.
Léo Léopold Hertz 준영
@UnixBasis, sí. Eche un vistazo a gnu.org/software/bash/manual/html_node/Pattern-Matching.html
Juliano
@Juliano Estoy bastante confundido con los patrones como: mv ~ / Linux /? (Tux * .png) ~ / Linux / New / mv ~ / Linux / + (Tux * .png) ~ / Linux / New / En el primero , Quería mover 0-1 Tux -photo. En este último, quería mover 1-n fotos de Tux. Se movieron todo. ¿Por qué? ¿Es posible mover una cantidad específica de fotos?
Léo Léopold Hertz 준영
97

Ponga lo siguiente en su .bashrc

shopt -s extglob

Extiende expresiones regulares. Luego puede mover todos los archivos excepto uno por

mv !(fileOne) ~/path/newFolder

Excepciones en relación con otros comandos.

Tenga en cuenta que, al copiar directorios, el flash de avance no se puede usar en el nombre como se observa en el hilo ¿Por qué extglob excepto romper excepto condición? :

cp -r !(Backups.backupdb) /home/masi/Documents/

así que Backups.backupdb/está mal aquí antes de la negación y no lo usaría ni para mover directorios debido al riesgo de usar mal, luego globos con otros comandos y otras posibles excepciones.

Léo Léopold Hertz 준영
fuente
3
Esta es realmente la respuesta correcta. La mía estaba completamente equivocada; Afortunadamente lo había usado en una carpeta con solo unos pocos archivos. Aquí hay más información sobre el método que muestra Masi: wiki.bash-hackers.org/syntax/pattern Vaya a "Lenguaje de patrón extendido" y encontrará más información al respecto. Gracias a @ paul-whittaker por señalar el problema.
mimoralea
Esta es una respuesta antigua pero sigue siendo válida. Estoy usando Ubuntu 18 y extglob parece estar habilitado de forma predeterminada (no lo compré). Utilicé el siguiente comando para mover todos los archivos del directorio actual a un archivo que también está dentro de este directorio, SIN incluir ninguna otra carpeta de archivo: mv !(arc*) archive_190629b
TonyG
70

Me gustaría seguir la forma tradicional de encontrar y xargs:

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png -print0 | 
    xargs -0 mv -t ~/Linux/New

-maxdepth 1hace que no busque de forma recursiva. Si solo te interesan los archivos, puedes decir -type f. -mindepth 1hace que no incluya la ~/Linux/Oldruta en sí misma en el resultado. Funciona con cualquier nombre de archivo, incluso con aquellos que contienen nuevas líneas incrustadas.

Un comentario señala que la -topción mv es probablemente una extensión GNU. Para sistemas que no lo tienen

find ~/Linux/Old -maxdepth 1 -mindepth 1 -not -name Tux.png \
    -exec mv '{}' ~/Linux/New \;
Johannes Schaub - litb
fuente
1
Upvoted ya que fomenta el aprendizaje de una herramienta poderosa, encontrar. Nota, para archivos con espacios en blanco esto no funcionará. Considere "encontrar -print0 | xargs -0" o de lo contrario renunciar a xargs: "encuentre [lo que dijo] -exec mv -t {} ~ / Linux / New \;"
JasonSmith
Si su comando mv no tiene la opción -t, entonces use "find ... -exec mv {} Linux / New \;" o "buscar ... | xargs -I {} mv {} Linux / New". La opción -t parece ser una extensión de GNU, que está bien para Linux, pero probablemente no en otros lugares.
Rob Kennedy el
jhs, oh, fallo de alguna manera pensé que los xargs se dividían en las nuevas líneas pero no en los espacios. parece que lo confundí con "leer" :) lo arreglaré
Johannes Schaub - litb
¡Muchas gracias por el increíble consejo! Iba a elegir algo porque apunta a la pregunta. Sin embargo, puedo sentir la utilidad de sus comandos más adelante, así que debo elegir la forma "buscar y xargs". Solo rocas. Gracias :)
Léo Léopold Hertz 준영
Camino a complicado. La respuesta de Masi es más completa, más fácil y por lo tanto más correcta
user637338
30

Una forma rápida sería modificar el nombre de archivo tux para que su comando de movimiento no coincida.

Por ejemplo:

mv Tux.png .Tux.png

mv * ~/somefolder

mv .Tux.png Tux.png
John T
fuente
no use " . ", ya que solo moverá archivos que tengan un "." en el nombre. Solo "*" es suficiente.
Juliano
1
Si lo cambia a *, también eliminará su archivo renombrado.
John T
66
@John T: No, el * glob no coincide con los archivos que comienzan con punto.
Bill Karwin el
Esta es la mejor respuesta con diferencia. No es necesario alterar o comentar esta respuesta. 100 puntos Muchas gracias. ¡Bien hecho!
Steve K
23

Creo que la forma más fácil de hacerlo es con backticks

mv `ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Editar:

Utilice la barra invertida con ls en su lugar para evitar usarlo con alias, es decir, principalmente ls tiene el alias como ls --color.

mv `\ls -1 ~/Linux/Old/ | grep -v Tux.png` ~/Linux/New/

Gracias @Arnold Roa

Rohail Abbas
fuente
1
¿Puedes explicar por qué lo usas grep -vallí?
Léo Léopold Hertz 준영
1
-v opción en grep excluye el resultado, es como tomar todo excepto Tux.png
Rohail Abbas
1
Esto es ciertamente intuitivo, pero las respuestas anteriores son mejores. Si está escribiendo un script, por ejemplo, esto requeriría que esté en el directorio correcto.
nJGL
@nJGL También podemos dar una ruta absoluta aquí, utilicé homedirectory (~) ya que la pregunta tenía esto
Rohail Abbas
@RohailAbbas Bastante justo. ✌️
nJGL
14

Para bash, la respuesta sth es correcta. Aquí está la sintaxis de zsh (mi shell de elección):

mv ~/Linux/Old/^Tux.png ~/Linux/New/

Requiere EXTENDED_GLOBque se establezca la opción de shell.

Juliano
fuente
3
¿Qué pasa si queremos excluir dos archivos?
mpen
13

Creo que esto es un poco más seguro y más fácil de usar para movimientos simples que excluyen ciertos archivos o directorios.

ls -1 | grep -v ^$EXCLUDE | xargs -I{} mv {} $TARGET
alex.pilon
fuente
Esta es la mejor solución para Busybox / ASH
Stuart Cardall
1
Esto funcionó para mí en una situación en la que tuve que mover todos los archivos excepto algunas carpetas a otro directorio
Umar Hayat
La -lopción lsincluirá una gran cantidad de información irrelevante en la línea de comando y resultará en la falla del comando mv.
jdhao
5

El siguiente no es un método 100% garantizado y no debe intentarse en absoluto para la creación de secuencias de comandos. Pero algunas veces es lo suficientemente bueno para un uso rápido de shell interactivo. Un archivo de archivo glob como

[abc]*

(que coincidirá con todos los archivos con nombres que comienzan con a, b o c) se puede negar insertando un carácter "^" primero, es decir

[^abc]*

A veces uso esto para no coincidir con el directorio "perdido + encontrado", como por ejemplo:

mv /mnt/usbdisk/[^l]* /home/user/stuff/.

Por supuesto, si hay otros archivos que comienzan con l, tengo que procesarlos después.

hlovdal
fuente
4
mv `find Linux/Old '!' -type d | fgrep -v Tux.png` Linux/New

El comando find enumera todos los archivos normales y el comando fgrep filtra cualquier Tux.png. Los backticks le dicen a mv que mueva la lista de archivos resultante.

David Norman
fuente
44
Nunca, jamás, evalúe encontrar como argumentos para otro comando. Cosas malas sucederán. Es posible que haya creado una vulnerabilidad. Utilice siempre el find -print0 | xargs -0 construcción o find -exec.
Juliano
3

¿Qué tal si mueve todo en la carpeta y luego simplemente mueve Tux.png de regreso?

No se me ocurre ninguna sintaxis de shell que diga "todo excepto ..." de manera improvisada.

David Z
fuente
3
ls ~/Linux/Old/ | grep -v Tux.png | xargs -i {} mv ~/Linux/New/'
aitor
fuente
1
Parece que a este comando le falta una parte y no funciona en mi computadora. ls ~/Linux/Old/ | grep -v Tux.png | xargs -I{} mv {} ~/Linux/New/funciona en su lugar.
Katherine Chen
3

Qué tal si:

mv $(echo * | sed s:Tux.png::g) ~/Linux/New/

Sin embargo, debes estar en la carpeta.

antibus
fuente
3

Uno puede omitir grep así:

ls ~/Linux/Old/ -QI Tux.png | xargs -I{} mv ~/Linux/Old/{} ~/Linux/New/
Arch Linux Tux
fuente
1

Esto podría ser más simple y fácil de recordar y funciona para mí.

mv $(ls ~/folder | grep -v ~/folder/exclude.png) ~/destination

Pakpoom Tiwakornkit
fuente