0

I am using xargs and rm with find in order to remove files that follow a specific pattern defined by find as follows:

touch file
find . -name file | xargs rm

Everything works fine with the above code, but if I enter the -i option to rm, then executing:

touch file
find . -name file | xargs rm -i

prints:

rm: remove regular empty file ‘./file7’? user@host:$

without letting me enter y or n. Thus the file is not removed.

What's the problem here?

I am also aware of the xargs -p parameter which works but it is more general. That is, it prompts user to execute the specific command, which is not user-friendly.

EDIT: While using it in a shell script, I've found out that it executes the command I want but it also prints find's result, which is not preferable.

Also, when I pass the ls file2 command to cmd variable, it does not specifically print the file2's specs. Same thing happens when I type rm -i file2 . It prompts me to delete every single file in the directory.

This is my script:

#!/bin/bash
touch file{1..9}      # Create 9 files named file1,file2...file9
echo -n 'command: '  # Prompt user
read -e cmd             # read command
find . -exec ${cmd} '{}' +  

The only solution I can think of is to prompt the user separately for their preferred pattern. Then store that pattern to a variable and pass it as an argument to find command's -name option.

Something like this:

#!/bin/bash
touch file{1..9}     # Create 9 files named file1,file2...file9
echo -n 'command: '  # Prompt user for command
read -e cmd          # read command
echo -n 'pattern: '  # Prompt user for pattern
read -e pattern
find . -name "$pattern" -exec ${cmd} '{}' +  

But even with this solution, find's output is still printed and if the pattern field is left empty (i.e., the user just does not want to use a pattern) then problems occur.

Any ideas?

5 Answers 5

4

xargs reads data from stdin. When you use rm -i rm also tries to read the answer from stdin (try touch test && echo y | r -i test ; ls test) but stdin is closed by xargs (I assume) so rm reacts as if you had pressed ctrl-d at the prompt.

Another solution might be find's -exec option:

touch test
find . -name test -exec rm -i {} \;
2

You can use the POSIX -ok option for find to have it ask you whether or not to proceed with a command (other than the prompt it's just like -exec)

touch file
find . -name 'file' -ok rm -f {} \;

Output

< rm ... ./file > ? _
1

The problem here is that the stdin (the standard input) for the command ran from xargs (in this case rm) is redirected from /dev/null, and the stdin is the file descriptor used by rm to obtain the user's confirmation.

You could use the -a option so that rm obtain the list of files from an intermediate file previously generated by the find command (the -a option makes xargs to let the stdin untouched), in any case, I understand this may not be what you really want since it requires the intermediate file. A more straight approach similar to what you wanted can be obtained with the command below:

for i in $(find . -name file); do rm -i "$i"; done

0
     Just try that command

    find . -type f -iname filename -delete


  it is better to delete the need file.

   -type f ----> specific the file type ( file or directory or etc. )
   -iname  ----> ignore the case sensitive ( test or Test)
   -delete ----> its one of find command option, its delete files  
0

I had a similar problem, and was surprised when the command

find . -type f -name "*.txt" | xargs rm

unexpectedly deleted read-only files that matched the pattern.

Only afterward did I find the explanation in the rm man page:

if a file is unwritable, standard input is a terminal, and the -f or --force option is not given, or the -i or --interactive=always option is given, rm prompts the user for whether to remove the file.

One of the conditions to get the prompt is that standard input is a terminal, which is not true when you are piping output from another command to rm.

IMPORTANT LESSON: if stdin is not a terminal, rm will remove read-only files without any warning!!

In my case, the solution was to modify the find command to only return writable files:

find . -type f -writable -name "*.txt" | xargs rm

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.