Un'altra risposta è forzare xargs
per elaborare i comandi in batch. Ad esempio a delete
i file 100
alla volta, cd
nella directory ed esegui questo:
echo *.pdf | xargs -n 100 rm
tl;dr
È una limitazione del kernel sulla dimensione dell'argomento della riga di comando. Usa un for
loop invece.
Origine del problema
Questo è un problema di sistema, relativo a execve
e ARG_MAX
costante. C'è molta documentazione a riguardo (vedi man execve, wiki di debian, dettagli su ARG_MAX).
Fondamentalmente, l'espansione produce un comando (con i suoi parametri) che supera ARG_MAX
limit.Sul kernel 2.6.23
, il limite è stato impostato a 128 kB
. Questa costante è stata aumentata e puoi ottenere il suo valore eseguendo:
getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic
Soluzione:uso di for
Ciclo
Usa un for
loop come consigliato su BashFAQ/095 e non c'è limite tranne RAM/spazio di memoria:
Prova a verificare che eliminerà ciò che ti aspetti:
for f in *.pdf; do echo rm "$f"; done
Ed eseguilo:
for f in *.pdf; do rm "$f"; done
Anche questo è un approccio portabile poiché i glob hanno un comportamento forte e coerente tra le shell (parte delle specifiche POSIX).
Nota: Come notato da diversi commenti, questo è davvero più lento ma più gestibile in quanto può adattarsi a scenari più complessi, ad es. dove si vuole fare più di una sola azione.
Soluzione:uso di find
Se insisti, puoi usare find
ma davvero non usare xargs in quanto "è pericoloso (rotto, sfruttabile, ecc.) durante la lettura di input non delimitato da NUL" :
find . -maxdepth 1 -name '*.pdf' -delete
Usando -maxdepth 1 ... -delete
invece di -exec rm {} +
consente find
eseguire semplicemente le chiamate di sistema richieste senza utilizzare un processo esterno, quindi più veloce (grazie al commento di @chepner).
Riferimenti
- Rispondo "Elenco argomenti troppo lungo". Come posso elaborare un elenco di grandi dimensioni in blocchi? @wooedge
- execve(2) - Pagina man di Linux (cerca ARG_MAX);
- Errore:elenco di argomenti troppo lungo nel wiki di Debian;
- Perché ricevo "/bin/sh:elenco di argomenti troppo lungo" quando passo argomenti tra virgolette? @ SuperUtente
find
ha un -delete
azione:
find . -maxdepth 1 -name '*.pdf' -delete
Il motivo per cui ciò si verifica è perché bash in realtà espande l'asterisco a ogni file corrispondente, producendo una riga di comando molto lunga.
Prova questo:
find . -name "*.pdf" -print0 | xargs -0 rm
Avviso: questa è una ricerca ricorsiva e troverà (ed eliminerà) anche i file nelle sottodirectory. Virata su -f
al comando rm solo se sei sicuro di non volere la conferma.
Puoi fare quanto segue per rendere il comando non ricorsivo:
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
Un'altra opzione è usare -delete
di find bandiera:
find . -name "*.pdf" -delete