Pass all elements in existing array to xargs
When you do
echo ${FILES[@]} | xargs -i mv '{}' /path/to/destination
xargs treats the entire line as a singe argument. You should split each element of the array to a new line, and then xargs
should work as expected:
printf "%s\n" "${FILES[@]}" | xargs -i mv '{}' /path/to/destination
Or if your filenames can contain newlines, you can do
printf "%s\0" "${FILES[@]}" | xargs -0 -i mv '{}' /path/to/destination
Related videos on Youtube
Matt
Mechatronics Engineering Student University of Waterloo
Updated on September 15, 2022Comments
-
Matt over 1 year
I am trying to pass an array of file paths to
xargs
to move them all to a new location. My script is currently working as follows:FILES=( /path/to/files/*identifier* ) if [ -f ${FILES[0]} ] then mv ${FILES[@]} /path/to/destination fi
The reason for having FILES as a array was because the
if [ -f /path/to/files/*identifier* ]
fails if the wildcard search returns multiple files. Only the first file is checked, because the move will be executed if any files exist.I want to replace
mv ${FILES[@]} /path/to/destination
with a line that passes${FILES[@]}
toxargs
to move each file. I need to usexargs
as I expect to have enough files to overload a singlemv
. Through research I have only been able to find the methods of moving files that I already know which search for the files again.#Method 1 ls /path/to/files/*identifier* | xargs -i mv '{}' /path/to/destination #Method 2 find /path/to/files/*identifier* | xargs -i mv '{}' /path/to/destination
Is there a way to can pass all elements in an existing array
${FILES[@]}
toxargs
?Below are methods I've tried and their errors.
Attempt 1:
echo ${FILES[@]} | xargs -i mv '{}' /path/to/destination
Error:
mv: cannot stat `/path/to/files/file1.zip /path/to/files/file2.zip /path/to/files/file3.zip /path/to/files/file4.zip': No such file or directory
Attempt 2: I wasn't sure if
xargs
can be executed directly or not.xargs -i mv ${FILES[@]} /path/to/destination
Error: No error message was output, but it hung after that line until I stopped it manually.
Edit: Find works
I tried the following and it moved all the files. Is this the best way to do it? And is it moving the files one by one, so the terminal is not overloaded?
find ${FILES[@]} | xargs -i mv '{}' /path/to/destination
Edit 2:
For future reference, I tested the accepted answer method versus the method in my first edit using
time()
. After running both methods 4 times, my method had an average of 0.659s and the accepted answer was 0.667s. So neither method works any faster than the other.-
fedorqui over 10 yearsOh sorry, I missed that part. Then I guess the best is to use
find . -name "..." -exec mv {} \;
having the pattern of the file in thename
.
-