简体   繁体   中英

Bash: Why mv won't move files under this for-loop?


Using a Bash script, I'd like to move a list of files by using a for-loop, not a while-loop (for testing purpose). Can anyone explain to me why mv always acts as file rename rather than file move under this for loop? How can I fix it to move the list of files?

The following works:

for file in "/Volumes/HDD1/001.jpg" "/Volumes/HDD1/002.jpg"
do
    mv "$file" "/Volumes/HDD2/"
done

UPDATE#1:
However, suppose that I have a sample_pathname.txt

cat sample_pathname.txt
"/Volumes/HDD1/001.jpg" "/Volumes/HDD1/002.jpg"

Why the following for-loop will not work then?

array=$(cat sample_path2.txt)
for file in "${array[@]}"
do
    mv "$file" "/Volumes/HDD2/"
done

Thanks.

System: OS X
Bash version: 3.2.53(1)

cat sample_pathname.txt

"/Volumes/HDD1/001.jpg" "/Volumes/HDD1/002.jpg"

The quotation marks here are the problem. Unless you need to cope with file names with newlines in them, the simple and standard way to do this is to list one file name per line, with no quotes or other metainformation.

vbvntv$ cat sample_pathname_fixed.txt
/Volumes/HDD1/001.jpg
/Volumes/HDD1/002.jpg

vbvntv$ while read -r file; do
>    mv "$file" "/Volumes/HDD2/"
> done <sample_pathname_fixed.txt

In fact, you could even

xargs mv -t /Volumes/HDD2 <sample_pathname_fixed.txt

(somewhat depending on how braindead your xargs is).

The syntax used in your example will not create an array... It is just storing the file contents in a variable named array.

IFS=$'\\n' array=$(cat sample_path2.txt)

If you have a text file containing filenames (each on separate line would be simplest), you can load it into an array and iterate over it as follows. Note the use of $(< file ) as a better alternative to cat and the parenthesis to initialize the contents into an array. Each line of the file corresponds to an index.

array=($(< file_list.txt ))

for file in "${array[@]}"; do
    mv "$file" "/absolute/path"
done

Update: Your IFS was probably not set correctly if the command at the top of the post didn't work. I updated it to reflect that. Also, there are a couple of other reliable ways to initialize an array from a file. But like you mentioned, if you are just piping the file directly into a while loop, you may not need it.

This is a shell builtin in Bash 4+ and a synonym of mapfile. This works great if its available.

readarray -t array < file

The 'read' command can also initialize an array for you:

IFS=$'\n' read -d '' -r -a array < file

use this:

for file in "/Volumes/HDD1/001.jpg" "/Volumes/HDD1/002.jpg"
do
    f=$(basename $file)
    mv "$file" "/Volumes/HDD2/$f"
done

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM