Removing files interactively with find and xargs
Asked Answered
R

3

12

I'm trying to pipe some files from the find command to the interactive remove command, so that I can double check the files I'm removing, but I've run into some trouble.

find -name '#*#' -print0 | xargs -0 rm -i

I thought the above would work, but instead I just get a string of "rm: remove regular file ./some/path/#someFile.js#? rm: remove regular file ./another/path/#anotherFile#?..."

Can someone explain to me what's exactly is happening, and what I can do to get my desired results? Thanks.

Rhombencephalon answered 18/8, 2013 at 19:24 Comment(0)
C
11

Can someone explain to me what's exactly is happening,

As the man page for xargs says (under the -a option): "If you use this option, stdin remains unchanged when commands are run. Otherwise, stdin is redirected from /dev/null."

Since you're not using the -a option, each rm -i command that xargs is running gets its stdin from /dev/null (i.e. no input is available). When rm asks whether to remove a particular file, the answer is effectively "no" because /dev/null gives no reply. rm receives an EOF on its input, so it does not remove that file, and goes on to the next file.

and what I can do to get my desired results?

Besides using find -exec as unxnut explained, another way to do it is to use the -o (or --open-tty) option with xargs:

find -name '#*#' -print0 | xargs -0 -o rm -i

That's probably the ideal way, because it allows rm -i to handle interactive confirmation itself, as designed.

Another way is to use the -p (or --interactive) option with xargs:

find -name '#*#' -print0 | xargs -0 -p rm

With this approach, xargs handles the interactive confirmation instead of having rm do it. You may also want to use -n 1, so that each prompt only asks about one file:

find -name '#*#' -print0 | xargs -0 -p -n 1 rm

The advantage of using xargs over find -exec is that you can use it with any command that generates the file path arguments, not just with find.

Creek answered 8/2, 2017 at 17:36 Comment(0)
M
14

You can do this by using exec option with find. Use the command

find . -name '#*#' -exec rm -i {} \;

xargs will not work (unless you use options such as -o or -p) because it uses stdin to build commands. Since stdin is already in use, you cannot input the response for query with rm.

Mercurate answered 18/8, 2013 at 19:28 Comment(2)
More detail: If xargs is reading items from stdin (i.e. if it's not using -a to read items from a file), then it redirects stdin from /dev/null for each command. So the prompt asking for confirmation cannot be answered by the user. man7.org/linux/man-pages/man1/xargs.1.htmlCreek
You should be using -ok: find -name '#*#' -ok rm {} \;Goniometer
C
11

Can someone explain to me what's exactly is happening,

As the man page for xargs says (under the -a option): "If you use this option, stdin remains unchanged when commands are run. Otherwise, stdin is redirected from /dev/null."

Since you're not using the -a option, each rm -i command that xargs is running gets its stdin from /dev/null (i.e. no input is available). When rm asks whether to remove a particular file, the answer is effectively "no" because /dev/null gives no reply. rm receives an EOF on its input, so it does not remove that file, and goes on to the next file.

and what I can do to get my desired results?

Besides using find -exec as unxnut explained, another way to do it is to use the -o (or --open-tty) option with xargs:

find -name '#*#' -print0 | xargs -0 -o rm -i

That's probably the ideal way, because it allows rm -i to handle interactive confirmation itself, as designed.

Another way is to use the -p (or --interactive) option with xargs:

find -name '#*#' -print0 | xargs -0 -p rm

With this approach, xargs handles the interactive confirmation instead of having rm do it. You may also want to use -n 1, so that each prompt only asks about one file:

find -name '#*#' -print0 | xargs -0 -p -n 1 rm

The advantage of using xargs over find -exec is that you can use it with any command that generates the file path arguments, not just with find.

Creek answered 8/2, 2017 at 17:36 Comment(0)
W
1

you can use this simple command to solve your problem.

find . -name '#*#' -delete
Wardlaw answered 27/10, 2021 at 11:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.