LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (http://www.linuxquestions.org/questions/linux-general-1/)
-   -   Command line : xargs and rm (http://www.linuxquestions.org/questions/linux-general-1/command-line-xargs-and-rm-4175456338/)

Seb-o-tronic 04-01-2013 04:20 AM

Command line : xargs and rm
 
Hello,

I'm currently studying Linux reading "Linux essentials" available on LPIC website.

On page 90, a comparison of "find ... -exec rm -i ..." and "find ... | xargs rm -i" is made.

I've just tried these two commands in order to understand how they works. The first one (using "-exec") seems to perfectly work, the second one does not.

As shown below, the rm command's "-i" option ask for a confirmation but I can not give an answer. The prompt reapears instead a way to give my deletion agreement.

Code:

[sebastien@louise LinuxEssentials]$ ll
total 4
-rwx------. 1 sebastien sebastien 12 Apr  1 11:15 myscript

Code:

[sebastien@louise LinuxEssentials]$ find . -amin -10  | xargs -r rm -i '{}'
rm: cannot remove `{}': No such file or directory
rm: cannot remove `.': Is a directory
rm: remove regular file `./myscript'? [sebastien@louise LinuxEssentials]$

Please, could you help me to understand what occures?

I'm not (yet?) a Linux professionnal. I'm an electronician who's interested in embedded Linux ... so, I have to learn! :)

I thank you so mutch in advance for your help.

linosaurusroot 04-01-2013 05:03 AM

If you remove the "-i" from these commands they both attempt non-interactive removal of files.

The one using -exec attempts one rm command per file to remove. The one with xargs writes a list of filenames to xargs where the xargs command puts as many of these text strings as possible into the arguments of an rm command (before doing 2nd and later commands if the input is large enough).

I suggest avoiding the xargs version as the files removed by rm are the result of text processing by xargs and may not be the original filenames as seen by find. For instance if root runs this in a cron job:
Code:

find /tmp -type f -name \*.mp3 -mtime +30 | xargs rm
The above can be manipulated by a malicious user intending to get /etc/passwd supplied as an argument to rm.
Code:

cd /tmp
mkdir  -p "problem /etc/passwd /stuff"
touch -t 197001011159 "problem /etc/passwd /stuff"/remove_me.mp3


Seb-o-tronic 04-01-2013 05:19 AM

Quote:

Originally Posted by linosaurusroot (Post 4922570)
If you remove the "-i" from these commands they both attempt non-interactive removal of files.

Sorry I forgot to paste my terminal screen - I've just edited my previous message.

What's appening is that "-i" ask for a confirmation but I cannot answer.

jpollard 04-01-2013 08:39 AM

There are two oversights -

1) the -i invokes the interactive removal, so you have to confirm that you want to remove the file.
Fixing this is easy - just take the -i option off.

2) the {} sequence is the internal identification used by find for the file name.
Since you are using xargs (which reads its parameter from stdin or the pipe) you don't use it on the rm command - xargs will put it there.

Seb-o-tronic 04-01-2013 09:24 AM

Sorry, English is a foreign language for me, I guess we don't understand :
- I understand how the command works. But it seems to not work as it should.
- I want to use interactive mode
- BUT (!) If the command above ask me to confirm deletion (as it should do, and does), it does not wait for my answer.

Thus, I understand how it should work but I don't understand why it does not wait for my answer.

Code:

rm: remove regular file `./myscript'?
--> I can not say "yes" or "no" : the prompt appear without waiting.

Code:

rm: remove regular file `./myscript'? [sebastien@louise LinuxEssentials]$

jpollard 04-01-2013 10:08 AM

That is because rm can't access stdin - it is coming from the find. If only one file is there, the script terminates as stdin is closed. If there are two files, the second file name is used to answer the prompt... and if it isn't "yes", then again it exits. If you have many files, then you should see the prompt for every other file... and unless one of the odd numbered files is "yes", nothing will be done.

linosaurusroot 04-01-2013 11:10 AM

Replace "-exec" with "-ok" to get interactive behaviour.

edwardcode 04-02-2013 11:35 AM

The proper syntax for the below command

find . -amin -10 | xargs -r rm -i '{}'

is

find . -amin -10 | xargs -I {} rm -i {}

jpollard 04-02-2013 04:47 PM

Quote:

Originally Posted by edwardcode (Post 4923558)
The proper syntax for the below command

find . -amin -10 | xargs -r rm -i '{}'

is

find . -amin -10 | xargs -I {} rm -i {}

Not with a pipe. the '{}' is only understood by the find process. What you get is "... xargs -I {} rm -i {}" and the error (well usually) "file not found".

rknichols 04-02-2013 04:59 PM

Quote:

Originally Posted by jpollard (Post 4923755)
Not with a pipe. the '{}' is only understood by the find process. What you get is "... xargs -I {} rm -i {}" and the error (well usually) "file not found".

Sorry, but the xargs command does allow you to define a string that will be replaced with an argument read from stdin, and "{}" is as good a string as any other.

whizje 04-02-2013 05:11 PM

Code:

bash-4.2$ ls tmp
test1.mp3  test2.mp3  test3.mp3
bash-4.2$ find tmp -maxdepth 1 -name '*.mp3' -maxdepth 1 | xargs -n1 -p rm
rm tmp/test3.mp3 ?...y
rm tmp/test2.mp3 ?...n
rm tmp/test1.mp3 ?...y
bash-4.2$ ls tmp
test2.mp3

-n1 passes one argument at the time
-p interactive mode

linosaurusroot 04-02-2013 11:32 PM

Quote:

Originally Posted by jpollard (Post 4923755)
Not with a pipe. the '{}' is only understood by the find process. What you get is "... xargs -I {} rm -i {}" and the error (well usually) "file not found".

The "-I {}" used with xargs prepares for the {} later in the command (although it's pointless in this case where all the filenames come at the end).


All times are GMT -5. The time now is 11:05 PM.