I want to get the last two lines of the find output and copy them somewhere. I tried
find . -iname "*FooBar*" | tail -2 -exec cp "{}" dest \;
but the output was "invalid option --2" for tail.
Also, my file or directory name contains spaces.
The following should work on absolutely any paths.
Declare a function to be able to use head
and tail
on NUL-separated output:
nul_terminated() {
tr '\0\n' '\n\0' | "$@" | tr '\0\n' '\n\0'
}
Then you can use it to get a NUL-separated list of paths from your search after passing through tail
:
find . -exec printf '%s\0' {} \; | nul_terminated tail -n 2
You can then pipe that to xargs
and add your options:
find . -iname "*FooBar*" -exec printf '%s\0' {} \; | nul_terminated tail -n 2 | xargs -I "{}" -0 cp "{}" "dest"
Explanation:
find
files in the current directory (.
) and below with a name containing foobar
(case insensitive because of the i
in -iname
);-exec
) a command to{}
) followed by a NUL character (\0
) individually (\;
);tr '\0\n' '\n\0'
);"tail -n 2
, "$@"
);tr '\0\n' '\n\0'
).The xargs
command is a bit harder to explain. It builds as many cp ... "dest"
commands as necessary to fit in the maximum command length of the operating system, replacing the {}
token in the command with the actual file name (-I "{}" ... "{}"
), using the NUL character as a separator when reading the parameters (-0
).
You can try
cp $(find . -iname "*FooBar*" | tail -2 ) dest
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With