Copying files from multiple directories into a single destination directory

前端 未结 4 2007
挽巷
挽巷 2021-01-24 09:14

There are multiple directories which contain a file with the same name:

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

N

相关标签:
4条回答
  • 2021-01-24 09:43

    This little BaSH script will do it both ways:

    #!/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
    

    And the output:

    $ 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
    
    0 讨论(0)
  • 2021-01-24 09:47
    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
    

    where file_list is a list of your files.

    0 讨论(0)
  • 2021-01-24 09:47

    You can achieve this with 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%/*}" removes all characters starting from /, basically, giving us the dirname
    • ${dir#*direct_} removes the direct_ prefix from dirname
    • ((++counter)) uses Bash arithmetic expression to pre-increment the counter

    See also:

    • Why you shouldn't parse the output of ls(1)
    • Get file directory path from file path
    • How to use double or single brackets, parentheses, curly braces
    0 讨论(0)
  • 2021-01-24 10:00

    It may not be quite what you want, but it will do the job. Use 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~
    

    If you really want to put part of the folder name in, you have to decide exactly what part you want. You could, of course, just replace the directory separator character with some other character, and put the whole path into the filename.

    0 讨论(0)
提交回复
热议问题