17

I have a list of files, with their full paths, one per line in a file "files.txt"

I was trying to move all of those files from their original location to a new directory.

I CDed into the directory where they live now and issued

for file in ~/Desktop/files.txt do mv $file ~/newfolder

but nothing happens. I am sure I am missing something obvious

Oliver Salzburg
  • 89,072
  • 65
  • 269
  • 311
Steve
  • 537

9 Answers9

18

bash won't read the contents of the file unless you tell it to.

for file in $(cat ~/Desktop/files.txt); do mv "$file" ~/newfolder; done
Nifle
  • 34,998
10

You need to tell your loop to read the file, otherwise it is just executing:

mv ~/Desktop/files.txt ~/newfolder

In addition, as nerdwaller said, you need separators. Try this:

while read file; do mv "$file" ~/newfolder; done < ~/Desktop/files.txt

If your paths or file names contain spaces or other strange characters, you may need to do this:

while IFS= read -r file; do mv "$file" ~/newfolder; done < ~/Desktop/files.txt

Notice the quotes " around the $file variable.

terdon
  • 54,564
5

If the filenames do not contain whitespace:

mv -t dest_dir $(< text.file)

is probably the most concise way.

If there is whitespace in the filenames

while IFS= read -r filename; do mv "$filename" dest_dir; done < test.file

is safe.

glenn jackman
  • 27,524
3

I usually do it with

cat filename | xargs -I {} mv {} /new/dir/path

but not sure right now it works with spaces in filenames.

Flo
  • 131
2

Try this:

python -c "import shutil; [shutil.move(_.strip(), 'new') for _ in open('files.txt').readlines()];"

Miao Xu
  • 21
0

BASH code (you can script this):

i=0
IFS=$'\n'                         ## split only on newlines
for line in $(cat files_test.txt)    
do
    echo "$line"
    let ++i                       ## increment counter
done
unset IFS                         ## reset IFS to default
printf 'total: %s lines\n' $i

Test (complex file names):

$ pwd; ls -l

  /mnt/Vancouver/domains/buriedtruth.com/docs
  total 5520
  -rw-r--r-- 1 victoria victoria    1537 Feb 14 11:10 files_test.txt

$ cat files_test.txt | wc -l
  12

$ i=0

$ IFS=$'\n'                         ## split only on newlines

$ for line in $(cat files_test.txt)    
  ## snip

file:///mnt/Vancouver/projects/files/andrighetto2010complex.pdf
file:///mnt/Vancouver/projects/files/florini1996evolution.pdf
file:///mnt/Vancouver/FC/Psychology/Lesson Plan -- The Story of the Third Wave.mp4
file:///mnt/Vancouver/Downloads/downloads.archived/UFO/Did the AAWSA program, AATIP really start in 2007%3F.pdf
file:///mnt/Vancouver/Downloads/downloads.archived/UFO/Outbound to the Moon -- with a UFO%3F [James Oberg -- Jul 2015; apollo-11-ufo-3].pdf
file:///mnt/Vancouver/Downloads/downloads.archived/UFO/Buzz Aldrin re Apollo 11  %22I saw this illumination....%22.mkv
file:///mnt/Vancouver/Downloads/downloads.archived/Ötzi %7C Otzi %7C Iceman/Unexplained Files S01E02 Livestock Mutilation & Curse of the Ice Mummy (cattle mutilations; Otzi; 2013).mkv
file:///mnt/Vancouver/Downloads/downloads.archived/UFO/Contact 2019 -- S01/contact.2019.s01e06.anatomy.of.a.cover.up (UFOs and nuclear sites).mkv
file:///mnt/Vancouver/Downloads/downloads.archived/UFO/Robert M. L. Baker -- Exocosmology  Gravitational Waves & Brain -- Location of Exobiological Intelligence -- Exoklima 2.0.mkv
file:///mnt/Vancouver/FC/Consciousness/Rethinking Consciousness -- QA with Michael Graziano [behavioralscientist.org].pdf
file:///mnt/Vancouver/Downloads/downloads.archived/60 Minutes/Nuremberg Prosecuter Ben Ferencz (60 Minutes S49E33, 2017) -- Transcript -- What the last Nuremberg prosecutor alive wants the world to know.pdf
file:///mnt/Vancouver/Downloads/downloads.archived/Economist -- Can Norway Help US Break the Reoffending Cycle?.mkv

$ unset IFS                         ## reset IFS to default
$ printf 'total: %s lines\n' $i
  total: 12 lines

Reference; https://askubuntu.com/questions/344407/how-to-read-complete-line-in-for-loop-with-spaces

0
#!/bin/bash

# Check if the correct number of arguments is provided
if [ $# -ne 2 ]; then
    echo "Usage: $0 <file_list> <destination_directory>"
    exit 1
fi

file_list="$1"
destination_directory="$2"

# Check if the file list exists
if [ ! -f "$file_list" ]; then
    echo "File list not found: $file_list"
    exit 1
fi

# Check if the destination directory exists
if [ ! -d "$destination_directory" ]; then
    echo "Destination directory not found: $destination_directory"
    exit 1
fi

# Read each filename from the file list and move it to the destination directory
while IFS= read -r filename; do
    if [ -f "$filename" ]; then
        echo "Moving $filename to $destination_directory"
        mv "$filename" "$destination_directory"
    else
        echo "File not found: $filename"
    fi
done < "$file_list"

echo "File move completed."

Save the script in a file, for example, move_files.sh. Make the script executable using the command chmod +x move_files.sh. Then you can run the script by providing the file list and the destination directory as arguments:

./move_files.sh <file_list> <destination_directory>

Replace <file_list> with the path to your file containing the list of filenames, and <destination_directory> with the path to the directory where you want to move the files.

Note: The script assumes that the filenames listed in the file are either absolute paths or relative paths to the current directory. If the file names are relative to a different directory, you may need to modify the script accordingly.

svp
  • 103
  • 2
-1

Possibly

mv -t dest_dir $(sed 's|^|"|;s|$|"|' text.file)

also deals with filenames with spaces while still using a single mv command and no loop. Untested.

-1

I did this with:

mv `cat file_list.txt` /dest/folder/name