0

I would like to search for all the nohup.out in my mounted filesystems, and delete them.

  1. There are some directories and files whose filenames contain space, so I think of xargs -0.

  2. To be safe, I would like to interactively delete them, i.e. be asked if I really want to delete them. So I think of rm -i and xargs -p

  3. I also would like to delete each found file seperately, so I think of xargs -n 1.

But the following command doesn't work in the way I hope.

locate  -i nohup.out | xargs -0 -n 1 -p rm -i

It doesn't prompt each file to be removed and ask for my permission.

I wonder why and what command works as I hope?

By the way my xargs version is xargs (GNU findutils) 4.4.2. Can it be the reason?

Tim
  • 101,790
  • locate is only as good as the db it looks up. If you haven't run updatedb in a while, locate will be near useless. You'll want to use find. Additionally, you don't specify what doesn't work the way you hope? – ffledgling Feb 28 '16 at 00:06
  • 1
    yes, I want to use locate after updatedb, because it is faster. My command doesn't prompt each file to be removed and ask for my permission – Tim Feb 28 '16 at 00:07
  • what's the output look like for you when you run it? I run xargs without passing the -i to rm and it works just fine. – ffledgling Feb 28 '16 at 00:12
  • 1
    AFAIK locate doesn't produce null-separated output by default, so you're creating a newline-separated list which xargs -0 will treat as a single argument, no? – steeldriver Feb 28 '16 at 00:23
  • @steeldriver: you may be right. – Tim Feb 28 '16 at 00:28
  • For locate vs find: http://unix.stackexchange.com/questions/60205/locate-vs-find-usage-pros-and-cons-of-each-other – Rui F Ribeiro Feb 28 '16 at 08:46

4 Answers4

4

Use find not locate

find . -name "nohup.out" | xargs -n 1 -p rm

When you add rm -i it acts as the input for the -p prompt

You can use find this way too

find . -name "nohup.out" -exec rm -i {} \;
Marware
  • 486
  • 3
  • 10
2

If you want interactive behaviour and prompting with xargs, you might want to do this instead:

locate  -i nohup.out | xargs -d '\n' -L1 -p rm
ffledgling
  • 1,379
  • what if spaces in filenames? – Tim Feb 28 '16 at 00:14
  • @Tim updated answer. see edit. – ffledgling Feb 28 '16 at 00:20
  • Thanks. why use -L1? Why not -n 1? – Tim Feb 28 '16 at 00:25
  • Can only one of xargs -p and rm -i be used, not both? When both, it seems answering yes doesn't commit a removal action. – Tim Feb 28 '16 at 00:34
  • @Tim, I usually wouldn't expect an interactive command to run through another command that probably starts it as a subshell. Empirically, it tried it and it didn't work, so I'm going to assume both can't be used together, at least not in this way. – ffledgling Feb 28 '16 at 00:39
  • are -L1 and -n 1 the same? – Tim Feb 28 '16 at 00:41
  • No they are not, the man page says -n specifies number of args passed to the command and -L specifies number of lines to be read from input. – ffledgling Feb 28 '16 at 00:42
  • here each line in the output of locate is treated as a argument by xargs, so are -L1 and -n 1 the same? – Tim Feb 28 '16 at 00:47
  • @Tim possibly, that's a subtlety I don't quite understand, you might want to create a fresh question about it. – ffledgling Feb 28 '16 at 00:49
2

But the following command doesn't work in the way I hope.

locate -i nohup.out | xargs -0 -n 1 -p rm -i

Of course if you are using xargs -0 then you must match that with locate -0.

It doesn't prompt each file to be removed and ask for my permission. I wonder why

xargs should read input from /dev/tty when prompting you. It works that way so that there is no conflict between the use of xargs's stdin for reading arguments from locate and reading responses for the -p option.

However, you are using xargs to run rm -i. The rm -i command also wants to read your input, which it will read from stdin. Hence it eats up part of xargs's input and things don't work how you expect.

and what command works as I hope?

If you are using Bash, this is one option:

xargs -a <(locate -0 -i nohup.out) -0 -n 1 -p rm -i

However, you can also do everything in find:

find / -depth -name nohup.out -ok rm -i '{}' ';'

Change ';' to '+' to delete more than one file at a time. This requirement and the various ways you can solve this problem are explained in the Texinfo manual for findutils.

James Youngman
  • 1,144
  • 5
  • 20
  • Thanks. Is -depth here necessary? – Tim Jun 06 '18 at 20:45
  • Strictly, no. But when removing things, you need to remove containing directories after their contents (else the removing fails). This means that in general using -depth is best. Since here we are using "rm" without "-r" we would not be able to remove a directory anyway. – James Youngman Jun 07 '18 at 13:34
  • Thanks. I don't observe the problem that rm -i "eats up part of xargs's input and things don't work how you expect." – Tim Jun 08 '18 at 03:48
  • You're right, I'd forgotten that I fixed this in http://git.savannah.gnu.org/cgit/findutils.git/commit/?id=6c40e5651 – James Youngman Jun 09 '18 at 15:48
1

POSIXly:

find /path/to/mounted_fs -xdev -type f -name nohup.out -exec rm -i {} +

-xdev limited find to search only in your mounted filesystems. Using -exec rm -i {} + like you use xargs but without issue with special characters in filename.


The problem with your command:

locate -i nohup.out | xargs -0 -n 1 -p rm -i

you told xargs to use \0 as input separator, but locate output did not use \0 but \n, so xargs would see locate output as a big string.

cuonglm
  • 153,898