【问题标题】:Copying files from multiple directories into a single destination directory将文件从多个目录复制到单个目标目录
【发布时间】:2017-11-11 14:41:51
【问题描述】:

有多个目录包含同名文件:

direct_afaap/file.txt
direct_fgrdw/file.txt
direct_sardf/file.txt
...

现在我想将它们提取到另一个目录 direct_new 并使用不同的文件名,例如:

[mylinux~ ]$ ls direct_new/
file_1.txt  file_2.txt  file_3.txt

我该怎么做?

顺便说一句,如果我想将原始目录中的部分名称放入文件名中,例如:

[mylinux~ ]$ ls direct_new/
file_afaap.txt  file_fgrdw.txt  file_sardf.txt

我能做什么?

【问题讨论】:

    标签: linux bash shell


    【解决方案1】:

    它可能不是您想要的,但它会完成这项工作。使用cp --backup=numbered <source_file> <destination_directory:

    $ find . -name test.sh
    ./ansible/test/integration/roles/test_command_shell/files/test.sh
    ./ansible/test/integration/roles/test_script/files/test.sh
    ./Documents/CGI/Code/ec-scripts/work/bin/test.sh
    ./Documents/CGI/Code/ec-scripts/trunk/bin/test.sh
    ./Test/test.sh
    ./bin/test.sh
    ./test.sh
    
    $ mkdir BACKUPS
    
    $ find . -name test.sh -exec cp --backup=numbered {} BACKUPS \;
    cp: './BACKUPS/test.sh' and 'BACKUPS/test.sh' are the same file
    
    $ ls -l BACKUPS
    total 28
    -rwxrwxr-x. 1 jack jack 121 Jun  9 10:29 test.sh
    -rwxrwxr-x. 1 jack jack  34 Jun  9 10:29 test.sh.~1~
    -rwxrwxr-x. 1 jack jack  34 Jun  9 10:29 test.sh.~2~
    -rwxrwxr-x. 1 jack jack 388 Jun  9 10:29 test.sh.~3~
    -rwxrwxr-x. 1 jack jack 388 Jun  9 10:29 test.sh.~4~
    -rwxrwxr-x. 1 jack jack  20 Jun  9 10:29 test.sh.~5~
    -rwxrwxr-x. 1 jack jack 157 Jun  9 10:29 test.sh.~6~
    

    如果你真的想把文件夹名称的一部分放进去,你必须确定你想要的部分。当然,您可以将目录分隔符替换为其他字符,然后将整个路径放入文件名中。

    【讨论】:

      【解决方案2】:
      while read -r line; do 
         suffix=$(sed 's/^.*_\(.*\)\/.*$/\1/' <<<$line)
         newfile=$(sed 's/\.txt/$suffix\.txt/' <<<$line)
         cp "$line" "~/direct_new/$newfile"
      done <file_list.txt
      

      其中 file_list 是您的文件列表。

      【讨论】:

        【解决方案3】:

        这个小 BaSH 脚本可以双向执行:

        #!/bin/sh
        #
        
        # counter
        i=0
        
        # put your new directory here
        # can't be similar to dir_*, otherwise bash will
        # expand it too
        mkdir newdir
        
        for file in `ls dir_*/*`; do
            # gets only the name of the file, without directory
            fname=`basename $file`
            # gets just the file name, without extension
            name=${fname%.*}
            # gets just the extention
            ext=${fname#*.}
        
            # get the directory name
            dir=`dirname $file`
            # get the directory suffix
            suffix=${dir#*_}
        
            # rename the file using counter
            fname_counter="${name}_$((i=$i+1)).$ext"
        
            # rename the file using dir suffic
            fname_suffix="${name}_$suffix.$ext"
        
            # copy files using both methods, you pick yours
            cp $file "newdir/$fname_counter"
            cp $file "newdir/$fname_suffix"
        done
        

        还有输出:

        $ ls -R
        cp.sh*
        dir_asdf/
        dir_ljklj/
        dir_qwvas/
        newdir/
        out
        
        ./dir_asdf:
        file.txt
        
        ./dir_ljklj:
        file.txt
        
        ./dir_qwvas:
        file.txt
        
        ./newdir:
        file_1.txt
        file_2.txt
        file_3.txt
        file_asdf.txt
        file_ljklj.txt
        file_qwvas.txt
        

        【讨论】:

        • 您不需要使用昂贵的basenamedirname。此外,解析ls 输出也不是一个好主意,只要通配就可以了。此外,无需提取后缀,因为它是固定的 (.txt)。请看我的answer
        【解决方案4】:

        您可以通过Bash parameter expansion 实现此目的:

        dest_dir=direct_new
        
        # dir based naming
        for file in direct_*/file.txt; do
          [[ -f "$file" ]] || continue # skip if not a regular file
          dir="${file%/*}"             # get the dir name from path
          cp "$file" "$dest_dir/file_${dir#*direct_}.txt"
        done
        
        # count based naming
        counter=0
        for file in direct_*/file.txt; do
          [[ -f "$file" ]] || continue # skip if not a regular file
          cp "$file" "$dest_dir/file_$((++counter)).txt"
        done
        
        • dir="${file%/*}" 删除从 / 开始的所有字符,基本上,给我们目录名
        • ${dir#*direct_} 从目录名中删除 direct_ 前缀
        • ((++counter)) 使用 Bash 算术表达式来预递增计数器

        另见:

        【讨论】:

          猜你喜欢
          • 2020-03-22
          • 1970-01-01
          • 2015-10-15
          • 1970-01-01
          • 1970-01-01
          • 2017-05-02
          • 2015-06-23
          • 2010-10-09
          • 2012-03-04
          相关资源
          最近更新 更多