I have a list of files inside directory1 and I want to move n number of files from that directory1 to directory2. When I try xargs like this it did not work.
ls -ltr | head -20 | mv xargs /directory2
Why we can't use xargs in middle? how to move n number of files to another directory in command line ?
CodePudding user response:
First, you should not use ls
in scripts. ls
is for humans, not for scripting. Second, the last command of your pipe tries to move a file named xargs
to /directory2
. Third, xargs
appends its inputs to the command. Even if you swap mv
and xargs
this will lead to execute mv /directory2 file1 file2 file3... file20
, instead of what you want: mv file1 file2 file3... file20 /directory2
. Finally, the -l
option of ls
will print more than just the file name (permissions, owner, group...); you cannot use it as mv
argument.
Your ls
options suggest that you want to move the 20 oldest files. Try:
while read -d '' -r time file; do
mv -- "$file" "/directory2"
done < <( stat --printf '%Y %n\0' * | sort -zn | head -zn20 )
stat --printf '%Y %n\0' *
prints the last modification time as seconds since epoch, followed by the file name, of all files in the current directory. Each record is terminated by the NUL
character, the only character that cannot be found in a file name. The -z
option of sort
and head
and the -d ''
option of read
instruct these utilities to use NUL
as the record separator instead of the default (newline). This way, the script should work even if some of your file names contain newlines.
If you prefer xargs
:
stat --printf '%Y\t%n\0' * | sort -zn | head -zn20 | cut -zf2- |
xargs -0I{} mv -- {} /directory2
CodePudding user response:
You can try this:
n=20
cd /path/to/directory1 || exit
files=(*)
mv -- "${files[@]:0:n}" /path/to/directory2
Also, you may consider reading this article: Why you shouldn't parse the output of ls