En Linux, ¿cómo eliminar todos los archivos, EXCEPTO el patrón * .txt?

74

Sé cómo eliminar todos los txtarchivos en el directorio actual por rm *.txt. ¿Alguien sabe cómo eliminar todos los archivos en el directorio actual EXCEPTO txtarchivo?

Arma de fuego
fuente
21
Como siempre, pruebe las respuestas dadas con un comando inofensivo como lsantes de intentar realmente llamar rm.
chepner
^ Este chico no le gusta vivir peligrosamente .. :)
jDub9

Respuestas:

111

Puedes usar find:

find . -type f ! -name '*.txt' -delete

O las características de globbing extendidas de bash:

shopt -s extglob
rm *.!(txt)

O en zsh:

setopt extendedglob
rm *~*.txt(.)
#  ||     ^^^ Only plain files
#  ||^^^^^ files ending in ".txt"
#  | \Except
#   \Everything
Kevin
fuente
Es posible que algunos de estos necesiten ser adaptados dependiendo de si tiene carpetas y qué quiere hacer con ellas.
Kevin
1
No debe *.!(txt)ser !(*.txt)?
Lri
@LauriRanta depende de lo que hay en la carpeta, a lo que no hemos recibido respuesta. Está bien como está si todos los archivos tienen extensiones, y rmse ahogarían si hubiera carpetas.
Kevin
Tengo un problema con los corchetes. Cuando uso el estilo globbing en un script bash, se queja de un error de sintaxis y los paréntesis. Sin embargo, hacerlo desde la CLI funciona.
CMCDragonkai
1
@izogfif compruebe que esto find . -type f ! -name "*.txt" | xargs -r rmfuncionaría en GNU \ xargs. El comando xargs BSD y UNIX puede no tener -r usted debe verificar su localman xargs
Ntwobike
10

Hay muchas maneras de hacerlo. pero la forma más simple sería (bash):

shopt -s extglob
rm !(*.txt)
Kent
fuente
10

Si solo desea eliminar todos los archivos excepto '* .txt', puede usar el siguiente comando:

$ find . -type f ! -name "*.txt" -exec rm -rf {} \;

pero si también desea eliminar directorios junto con los archivos, puede usar esto:

$ find . ! -name "*.txt" -exec rm -r {} \;

Sagar Rakshe
fuente
4

Una solución sin find:

mv dir/*.txt otherdir/
rm -r dir
mv otherdir dir

Esto debería funcionar en todo tipo de proyectiles.

michas
fuente
3

Puedes usar grep invertido y xargs

ls | grep -v .txt$| xargs rm
rjv
fuente
ls | grep -v *.txt | xargs rmfunciona igual de bien
phillipsk
@phillipsk grep -v *.txtfuncionará solo si hay exactamente un .txtarchivo. Si no hay ninguno, grepse usará *.txtcomo patrón; si hay más de uno, buscará el primer nombre de archivo dentro de todos los demás .txtarchivos, ignorando la salida de ls. (Los resultados exactos pueden depender de las opciones glob de la concha.)
JigglyNaga
.txt$coincidirá con cadenas que terminan txtindependientemente del punto. Porque greptoma la expresión regular como parámetro. Por lo tanto, los archivos a.txty aatxty a-txttodos coincidirán con esta expresión. La expresión correcta debe ser ls | grep -v \\.txt$ | xargs --no-run-if-empty rm. Para personas curiosas: si quieres jugar con la expresión de forma segura, utiliza esta expresión de prueba ls | grep \\.txt$ | xargs --no-run-if-empty echo(nota: no hay -vbandera y rm=>echo). Nota 2: es posible que haya notado una doble barra invertida. Uno es para expresiones regulares, otro es para bash para escapar de la barra oblicua.
Dimitry K
1

Simplemente haz:

rm $(ls -I "*.txt" ) # Elimina el tipo de archivo excepto * .txt

Del mismo modo, si necesita eliminar "excepto uno o más tipos de archivo", haga lo siguiente:

rm $(ls -I "*.txt" -I "*.pdf" ) # Elimina tipos de archivos excepto * .txt y * .pdf

Surya
fuente
¡Bienvenido a StackExchange! La -Iopción podría ser útil, pero vea por qué no analizar ls . ¿Y qué logra el | xargs? Sin ningún argumento, simplemente se ejecuta echoen toda su entrada.
JigglyNaga
¿Qué se xargssupone que debe lograr?
dhag
Gracias, xargs no fue útil en el caso anterior, lo he corregido ahora.
Surya
0

Esto también funciona para eliminar todos los archivos y carpetas ocultos (punto) excepto el indicado ( .mydir):

rm -rf $(ls -aI ".mydir")
Chetabahana
fuente