Que tal rm -r a*/* ? Isso deve resolver seu problema.
Estou tentando executar o seguinte comando
ls -d a* | xargs -i sudo rm -rf {}/*
O problema é que quando eu adiciono a parte /* , o comando não funciona. Eu quero remover o conteúdo do diretório (não o próprio diretório).
Comandos como rm dependem do shell para expandir os curingas, então você precisa invocar um shell em algum lugar.
Talvez
ls -d a* | xargs -i sh -c sudo rm -rf {}/*
( Aviso : eu não testei nenhum desses comandos. Pode haver erros de digitação ou erros. Tente tudo com echo ou ls e não sudo primeiro. )
Recomendação geral: xargs raramente é a maneira mais simples de fazer alguma coisa. Sem -i (que é obsoleto, use o portable -I {} ), xargs espera um formato de entrada que nenhuma ferramenta padrão ou comum produz. Com -I , xargs tem algum uso, mas se você estiver canalizando find para ele, find -exec será mais simples.
Você precisa de um shell para expandir {}/* e esse shell deve agir após {} ter sido substituído por um caminho real. Uma solução simples é fazer o processamento linha por linha no shell. Observe o uso de três padrões para capturar todos os arquivos em um diretório, pois * omite arquivos de ponto; Não importa se alguns dos padrões não correspondem a nenhum arquivo, pois rm -f ignora qualquer argumento que não faça referência a um arquivo existente.
… |
while read -r line; do
sudo rm -rf -- "$line"/* "$line"/.[!.]* "$line"/..?*
done
O Xargs não é usado aqui, já que você precisa processar os arquivos um por um de qualquer maneira, a fim de fazer com que o shell realize a globbing. No entanto, como a técnica geral pode ser útil, aqui está uma maneira de enviar nomes de arquivos de volta para um shell a partir do xargs. O _ é o argumento $0 para o shell (é necessário, em parte, incomodar-se em colocar $0 em qualquer argumento subsequente e garantir que tudo funcione mesmo se $1 começar com - e assim seriam tratados como uma opção para o shell). Existem duas abordagens aqui: ou ter o loop do shell sobre seus argumentos, ou dizer ao xargs para passar um único argumento para cada invocação do shell.
… | xargs -I {} sudo sh -c 'for x; do rm -rf -- "$x"/* "$x"/.[!.]* "$x"/..?*; done' _ {}
… | xargs -I {} -n 1 sudo sh -c 'rm -rf -- "$1"/* "$1"/.[!.]* "$1"/..?*' _ {}
Suponho que ls -d a* seja um exemplo de brinquedo e que você tenha um comando mais complexo que produza um nome de arquivo por linha. Observe que ls -d a* não funcionará lá, pois a maioria das implementações ls não exibe caracteres não imprimíveis de forma transparente. Se o … for um comando find, use -exec , como em
find a* -exec sh -c 'rm -rf -- "$1"/* "$1"/.[!.]* "$1"/..?*' _ {} \; -prune
Outra opção é usar um loop de shell em vez de invocar xargs.
E.G.
ls -d a* | while read dir; do sudo rm -rf "$dir"/*; done;
Principalmente por exemplo, você também pode combinar as duas técnicas colocando uma construção shell no meio de um pipeline:
ls -d a* | while read dir; do ls -d "$dir"/*; done | xargs -d \n rm -rf
A opção -d para xargs apenas especifica que o delimitador entre os argumentos é uma nova linha, o que evita problemas potencialmente catastróficos com nomes de arquivos que contêm espaços (por exemplo deadly / file )