Justificação
Esta é minha tentativa de criar um comando que funcione com qualquer diretório e nome (s) de arquivo. Em geral, os caminhos no Linux (e nomes nos sistemas de arquivos) podem conter qualquer caractere, mas nulo ( 0x00 ) e / . Caracteres problemáticos podem ser " " (espaço), qualquer outro caractere branco, ' , " , nova linha, outros caracteres não imprimíveis. Portanto, é importante:
- abandonam ferramentas que substituem alguns caracteres por outras (por exemplo, muitas implementações de
ls imprimem ? para não-imprimíveis);
- passa todos os nomes como sequências terminadas em nulo (escolha ferramentas que possam analisá-las);
- cite corretamente.
Eu fui inspirado pela discussão em esta outra resposta .
Comandos reais
Versão de teste, serão apenas ls os arquivos que seriam removidos:
find -type d -exec sh -c 'find "$0" -maxdepth 1 -mindepth 1 -type f -exec stat --printf "%s %nfind -type d -exec sh -c 'find "$0" -maxdepth 1 -mindepth 1 -type f -exec stat --printf "%s %nfind -type d -exec '# Find all directories under (and including) the current one.' \
sh -c ' '# In every directory separately...' \
find "$0" -maxdepth 1 -mindepth 1 -type f -exec '# ...find all files,...' \
stat --printf "%s %nfind -type d -exec sh -c 'find "$0" -maxdepth 1 -mindepth 1 -type f -exec stat --printf "%s %nfind -type d -exec sh -c 'find "$0" -maxdepth 1 -mindepth 1 -type f -exec stat --printf "%s %nfind -type d -exec '# Find all directories under (and including) the current one.' \
sh -c ' '# In every directory separately...' \
find "$0" -maxdepth 1 -mindepth 1 -type f -exec '# ...find all files,...' \
stat --printf "%s %n%pre%" \{\} + | # ...get their sizes and names,...
sort -znr | # ...sort by size...
tail -zn +2' '# ...and discard the "biggest" entry.' \
{} \
\; | # (All the directories have been processed).
cut -zf 2- -d " " | # Then extract filenames...
xargs -0r ls -l # ...and ls them (rm in the working version).
" \{\} + | sort -znr | tail -zn +2' {} \; | cut -zf 2- -d " " | xargs -0r rm
" \{\} + | sort -znr | tail -zn +2' {} \; | cut -zf 2- -d " " | xargs -0r ls -l
" \{\} + | # ...get their sizes and names,...
sort -znr | # ...sort by size...
tail -zn +2' '# ...and discard the "biggest" entry.' \
{} \
\; | # (All the directories have been processed).
cut -zf 2- -d " " | # Then extract filenames...
xargs -0r ls -l # ...and ls them (rm in the working version).
" \{\} + | sort -znr | tail -zn +2' {} \; | cut -zf 2- -d " " | xargs -0r rm
" \{\} + | sort -znr | tail -zn +2' {} \; | cut -zf 2- -d " " | xargs -0r ls -l
Sim, estou usando ls aqui, apesar do que acabei de dizer. Isso ocorre porque ls output não está sendo analisado mais. Estou usando apenas para exibir o resultado. Se acontecer de você ter diretórios ou arquivos com caracteres problemáticos em seus nomes, você observará o comportamento de ls , que deve convencê-lo a nunca analisar ls (a menos que você saiba que está absolutamente seguro disso). Ainda assim, os nomes problemáticos passarão até ls e esse é o ponto.
Entenda a versão de teste (veja abaixo algumas explicações) e experimente antes de deixar a versão de trabalho (logo abaixo) remover seus arquivos. Lembre-se de que sou apenas um cara aleatório na Internet.
Versão de trabalho, ele removerá seus arquivos:
%pre%
Explicação
Aqui está a versão de testes dividida em várias linhas (embora ainda seja uma linha para bash ; note que eu uso esse truque para comentários inline):
%pre%
Técnicas usadas, obstáculos superados:
- As ferramentas que analisam strings são instruídas a trabalhar com sequências terminadas com nulo:
-
stat --printf "…sort -z" ;
-
tail -z , cut -z , xargs -0 … ;
-
find -print0 ;
-
sh -c '…' (não é necessário neste exemplo, mas é muito comum em geral, portanto eu menciono isso de qualquer maneira).
-
find -exec é o caminho para usar pipes dentro de find -type d -exec sh -c 'find "{}" … .
-
" será quebrado para o nome do diretório contendo find -type d -exec sh -c 'find "$0" … ' {} \; ; {} funciona bem.
-
find na instrução \{\} interna tem escape ( find ) para evitar que o% externocut os substitua.
-
tail poderia seguir imediatamente cut , ele executaria um find por diretório. Colocá-lo fora do exterior cut faz com que um único -r faça todo o corte de uma só vez.
- A opção
xargs para ls impede que rm ( xargs na versão de trabalho) seja executado quando não há entrada para %code% .