Xargs and also rm with a *

I am attempting to execute the adhering to command

ls -d a* | xargs -i sudo rm -rf {}/*

The trouble is that when I add the /* component the command does not function. I intend to remove the directory site materials (not the directory site itself).

2019-05-13 05:15:27
Source Share
Answers: 4

Commands like rm rely upon the shell to expand wildcards, so you would certainly require to invoke a shell someplace.


 ls -d a* | xargs -i sh -c sudo rm -rf {}/*
2019-05-17 18:07:01

What concerning rm -r a*/*? This need to address your concern.

2019-05-17 18:02:55

( Warning : I have not examined any one of these commands. There might be typos or mistakes. Attempt every little thing with echo or ls and also no sudo first.)

General suggestions : xargs is hardly ever the most basic means to do something. Without -i (which is deprecated incidentally, make use of the mobile -I {} rather), xargs anticipates an input layout that no typical or usual device generates. With -I, xargs does have some usage, though if you are piping find right into it, find -exec is less complex.

You require a shell to expand {}/*, which shell has to act after {} has actually been changed by one real course. A straightforward remedy is to do the line - by - line handling in the shell. Keep in mind making use of 3 patterns to record all the documents in a directory site as * leaves out dot documents ; no matter if several of the patterns do not match any kind of documents, as rm -f overlooks any kind of argument that does not reference an existing documents.

… |
while read -r line; do
  sudo rm -rf -- "$line"/* "$line"/.[!.]* "$line"/..?*

Xargs is no usage below given that you need to refine the documents individually anyhow at some time, so as to get the shell to execute the globbing. As the basic strategy can be valuable nonetheless, below is a means to feed documents names back right into a shell from xargs. The _ is the $0 argument to the shell (it exists partly not to need to trouble to stick $0 back onto any kind of succeeding argument, and also to make certain that every little thing functions also if $1 starts with a - therefore would certainly or else be dealt with as an alternative to the shell). There are 2 strategies below : either have the shell loop over its debates, or inform xargs to pass a solitary argument per shell conjuration.

… | 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"/..?*' _ {}

I'm thinking that ls -d a* is a plaything instance which you have an extra intricate command that generates one documents name per line. Keep in mind that ls -d a* would certainly not function there, as the majority of ls executions do not result nonprintable personalities transparently. If the is a locate command, usage -exec, as in

find a* -exec sh -c 'rm -rf -- "$1"/* "$1"/.[!.]* "$1"/..?*' _ {} \; -prune
2019-05-17 18:01:28

Another alternative is to make use of a shell loop as opposed to conjuring up xargs in all.


ls -d a* | while read dir; do sudo rm -rf "$dir"/*; done;

Mostly for instance, you can additionally incorporate both strategies by placing a shell construct in the center of a pipe:

ls -d a* | while read dir; do ls -d "$dir"/*; done | xargs -d \\n rm -rf

The -d alternative to xargs simply defines that the delimiter in between debates is a newline, which stays clear of possibly tragic troubles with filenames which have rooms (as an example deadly / file)

2019-05-17 17:54:45