Look at Stephane's answer for the best method, take a look at my answer for reasons not to use the more obvious solutions (and reasons why they are not the most efficient).
You can use the -I
option of xargs
:
find /tmp/ -ctime -1 -name "x*" | xargs -I '{}' mv '{}' ~/play/
Which works in a similar mechanism to find
and {}
. I would also quote your -name
argument (because a file starting with x
in the present directory would be file-globed and passed as an argument to find - which will not give the expected behavior!).
However, as pointed out by manatwork, as detailed in the xargs
man page:
-I replace-str
Replace occurrences of replace-str in the initial-arguments with
names read from standard input. Also, unquoted blanks do not
terminate input items; instead the separator is the newline
character. Implies -x and -L 1.
The important thing to note is that -L 1
means that only one line of output from find
will be processed at a time. This means that's syntactically the same as:
find /tmp/ -ctime -1 -name "x*" -exec mv '{}' ~/play/
(which executes a single mv
operation for each file).
Even using the GNU -0
xargs argument and the find -print0
argument causes exactly the same behavior of -I
- this is to clone()
a process for each file mv
:
find . -name "x*" -print0 | strace xargs -0 -I '{}' mv '{}' /tmp/other
.
.
read(0, "./foobar1/xorgslsala11\0./foobar1"..., 4096) = 870
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fbb82fad000
open("/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26066, ...}) = 0
mmap(NULL, 26066, PROT_READ, MAP_SHARED, 3, 0) = 0x7fbb82fa6000
close(3) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fbb835af9d0) = 661
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 661
--- SIGCHLD (Child exited) @ 0 (0) ---
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fbb835af9d0) = 662
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 662
--- SIGCHLD (Child exited) @ 0 (0) ---
.
.
.
You can use standard globbing on the rm
command:
rm -- *\ *
This will delete any file whose name contains a space; the space is escaped so the shell doesn't interpret it as a separator. Adding --
will avoid problems with filenames starting with dashes (they won’t be interpreted as arguments by rm
).
If you want to confirm each file before it’s deleted, add the -i
option:
rm -i -- *\ *
Best Answer
As you're already using that non-standard
1M
, chances are yourfind
implementation also supports-delete
. So, simply use:Where supported, that's by far the safest and most efficient.
If you insist on using
xargs
andrm
withfind
, just add-print0
in your command:(
-print0
and-0
are non-standard, but pretty common.-r
(to avoid runningrm
at all iffind
doesn't find anything) is less common, but if yourxargs
doesn't support it, you can just omit it, asrm
with-f
won't complain if called without argument).The standard syntax would be:
Other way:
(that's safer than
-exec
/xargs -0
and would work with very deep directory trees (where full file paths would end up larger thanPATH_MAX
), but that's also non-standard, and runs at least onerm
for each directory that contains at least one big file, so would be less efficient).From
man find
: