Bash: Loop over files listed in a text file and move them

后端 未结 6 1411
慢半拍i
慢半拍i 2021-02-15 00:01

I have a directory (directory A) with 10,000 files in it. I want to move some of them to directory B and the others to directory C. I made a text file that contains the names o

相关标签:
6条回答
  • 2021-02-15 00:13

    Using bash, having a huge filelist containing strings with leading and/or closing spaces I'd propose:

    less 'file-list.txt' | while read -r; do mv "$REPLY" /Volumes/hard_drive_name/new_destination_directory_name; done
    

    see:

    • How can I display the contents of a text file on the command line?
    • read -r vs read -r line and IFS
    • why REPLY variable in read builtin skip white space?
    0 讨论(0)
  • 2021-02-15 00:14

    you can move 1000 or 1000 user directory without take much time where thousand of user directory exist.

    cat deleteduser | while read i;  do mv -vv $i ../deleted_user; done; 
    deleteuser= user name list
    ../deleted_user= destination dir
    
    0 讨论(0)
  • 2021-02-15 00:15

    BASH FAQ entry #1: "How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?"

    If the filename will remain the same then the second argument to mv can be just the directory.

    0 讨论(0)
  • 2021-02-15 00:21

    You have to use BASH? What about Perl or Kornshell? The problem here is that Bash doesn't have hash keyed arrays (Kornshell and Perl do). That means there's no simple way to track what files go where. Imagine in Perl:

    my %directoryB;   #Hash that contains files to move to Directory B
    my %directoryC;   #Hash that contains files to move to Directory C
    
    open (TEXT_FILE_B, "textFileB") or die qq(Can't open "textFileB");
    while (my $line = <TEXT_FILE_B>) {
        chomp $line;
        $directoryB{$line} = 1;
    }
    close TEXT_FILE_B;
    
    open (TEXT_FILE_C, "textFileC") or die qq(Can't open "textFileC");
    while (my $line = <TEXT_FILE_C>) {
        chomp $line;
        $directoryC{$line} = 1;
    }
    close TEXT_FILE_C;
    

    The above lines create two hashes. One for files that need to be moved to Directory B and one for files that need to be moved to Directory C. Now, all I have to do is look at my hash and decide:

    foreach my $file (@directory) { #A little cheating here...
       if (exists $directoryB{$file}) {
           move ($file, $directoryB);
       } elsif (exists $directoryC{$file}) {
           move ($file, $directoryC)
    }
    

    My if statements can now look to see if a key has been defined in that hash. If it has, I know the file can be moved into that directory. I only have to read the two text files once. After that, my two hashes will store which files move to one directory and which to the other.


    However, we don't have hashes, so we'll use grep to see if the file name is in the directory. I'll assume that you have one file name on each line.

    ls | while read file
    do
       if grep -q "^${file}$" textFileB
       then
           mv $file $directoryB
       elif grep -q "^${file}$" textFileC
       then
           mv $file $directoryC
       fi
    done
    

    The grep -q will search your two text files to see if the matching file is there. If it is, it'll move the file to that directory. It's not very efficient since it has to search the entire text file each and every time. However, it's pretty efficient, and you're only talking about 10,000 files, so the whole operation should only take a few minutes.

    0 讨论(0)
  • 2021-02-15 00:28

    directory of the script should be the your location of the files

    TO_B=file1.txt
    TO_C=file2.txt
    
    for file in $TO_B
    do
    mv ${file} B/
    done
    
    for file in $TO_C
    do
    mv ${file} C/
    done
    
    0 讨论(0)
  • 2021-02-15 00:31
    cat file-list.txt | while read i; do
       # TODO: your "mv" command here.  "$i" will be a line from
       # the text file.
    done
    
    0 讨论(0)
提交回复
热议问题