【问题标题】:Bash: Loop over files listed in a text file and move themBash:循环遍历文本文件中列出的文件并移动它们
【发布时间】:2011-09-27 20:07:02
【问题描述】:

我有一个目录(目录 A),里面有 10,000 个文件。我想将其中一些移动到目录 B,而将其他移动到目录 C。我创建了一个文本文件,其中包含我要移动到目录 B 的所有文件的名称,另一个包含我想要的所有文件的名称移动到目录 C。如何编写 bash for 循环将这些文件移动到新目录。

伪代码:

对于 textfileB 中的文件:
将文件从目录 A 移动到目录 B

对于 textfileC 中的文件:
将文件从目录 A 移动到目录 C

很抱歉,如果在其他地方问过这个问题,但我花了几个小时试图学习 bash,但我就是不明白。我无法在另一个我能理解的线程中找到足够相似的内容(也许我只是不知道正确的搜索词)。

我得到了类似的东西,但我无法让它工作:

FILES=[dont' know what goes here? An array? A list?  

我可以只说明文本文件名吗?如果可以,文件必须是什么格式? name1.ext、name2.ext 或 name1.ext name2.ext]

for f in $FILES; do mv $f /B/$f [not sure about the second argument for mv]; done

谢谢

顺便说一句 Mac OSX 10.6.8(雪豹) 苹果终端 v. 2.1.2 / 273.1 重击 3.2

【问题讨论】:

    标签: macos bash file for-loop move


    【解决方案1】:

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

    如果文件名保持不变,那么mv 的第二个参数可以只是目录。

    【讨论】:

    • 那个 BASH 常见问题解答非常棒。再次感谢您确保有大量链接。 :)
    【解决方案2】:
    cat file-list.txt | while read i; do
       # TODO: your "mv" command here.  "$i" will be a line from
       # the text file.
    done
    

    【讨论】:

    • 谢谢。这行得通。对于其他人,这是完整的命令,我将其作为一行输入:cat list_of_files_with.txt |读我的时候;做 mv $i /Volumes/hard_drive_name/new_destination_directory_name;完成
    • @AquaT33nFan - 我会将"$i" 放在引号中,这样您就可以处理带有空格和其他通常不会出现在命令行中的字符的文件名。
    • 恭喜,您刚刚收到UUoCA
    • @Fredrik - 如果增加可读性真的没用吗?我发现像(while read i; do whatever; done) < file-list.txt 这样的东西是“向后”阅读的。此外,额外的上下文切换和 cat 二进制文件的加载将非常便宜,因为您不会注意到当前硬件的差异。
    • @asveikau - “无用”在这里可能是一个过于强烈的词,但我认为您评论中的方法优于 cat ... | 方法。而且由于*NIX 是一个非常漂亮的操作系统,您不会想浪费进程,是吗? ;-)
    【解决方案3】:

    脚本的目录应该是文件的位置

    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
    

    【讨论】:

    • "...在文本文件中列出..."
    • 您是否缺少$(cat $TO_B)
    • @sarnold 使用for i in $(cat $TO_B) 将无法正确处理带有空格的文件名。这就是我更喜欢我的答案的原因之一,cat filename | while read i
    【解决方案4】:

    你必须使用 BASH? Perl 或 Kornshell 呢?这里的问题是 Bash 没有散列键控数组(Kornshell 和 Perl 有)。这意味着没有简单的方法可以跟踪哪些文件去了哪里。想象一下 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;
    

    以上行创建了两个哈希。一个用于需要移动到目录 B 的文件,另一个用于需要移动到目录 C 的文件。现在,我所要做的就是查看我的哈希并决定:

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

    我的 if 语句现在可以查看是否在该哈希中定义了一个键。如果有,我知道该文件可以移动到该目录中。我只需要阅读这两个文本文件一次。之后,我的两个哈希值将存储哪些文件移动到一个目录,哪些文件移动到另一个目录。


    但是,我们没有哈希,所以我们将使用grep 来查看文件名是否在目录中。我假设你在每一行都有一个文件名。

    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
    

    grep -q 将搜索您的两个文本文件以查看是否存在匹配文件。如果是,它会将文件移动到该目录。它不是很有效,因为它每次都必须搜索整个文本文件。但是,它的效率很高,而且您只是在谈论 10,000 个文件,因此整个操作应该只需要几分钟。

    【讨论】:

      【解决方案5】:

      您可以移动 1000 或 1000 个用户目录,而无需花费太多时间来存在数千个用户目录。

      cat deleteduser | while read i;  do mv -vv $i ../deleted_user; done; 
      deleteuser= user name list
      ../deleted_user= destination dir
      

      【讨论】:

        【解决方案6】:

        使用 bash,有一个巨大的文件列表,其中包含带有前导和/或关闭空格的字符串,我建议:

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

        见:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-16
          • 2014-11-19
          • 2013-04-18
          • 1970-01-01
          • 2012-07-25
          • 1970-01-01
          相关资源
          最近更新 更多