File Handling and making directories to match in bash

56 Views Asked by At

I have these files: File_1.2.txt, File_1.5.txt, File_2.3.txt, and File_4.7.txt.

I want to make directories for them and sort them into the directories, like below.

Dir_001 -> File_1.2.txt File_1.5.txt 

Dir_002 -> File_1.2.txt File_2.3.txt

Dir_003 -> File_2.3.txt 

Dir_004 -> File_4.7.txt 

Dir_005 -> File_1.5.txt 

Dir_007 -> File_4.7.txt

So a directory is made for each number used by the files and all files containing the matching number of the directory are sorted into it.

2

There are 2 best solutions below

2
On BEST ANSWER
#!/bin/bash

# If there are no files match File_*.*.txt
# replace File_*.*.txt by empty string
shopt -s nullglob 

for i in File_*.*.txt; do
  echo "processing file $i"
  IFS="_." read foo num1 num2 foo <<< "$i"
  printf -v dir1 "Dir_%03d" "$num1"
  printf -v dir2 "Dir_%03d" "$num2"
  mkdir -pv "$dir1" "$dir2"
  cp -v "$i" "$dir1"
  cp -v "$i" "$dir2"
done
8
On

You should at least have tried this yourself. Just copying other people's code is not a good way of learning.

There are several ways of doing this, here is mine, where is yours?

#!/bin/bash

function make_dir
{
    #name="Dir00$1"
    # Cribbed from the answer given by @Cyrus
    printf -v name "Dir_%03d" "$1"

    echo "$name"
    if [[ ! -d $name ]]
    then
        mkdir "$name"
    fi
}

# I don't need an array here, but I have no idea where these filenames come from
filenames=(File_1.2.txt File_1.5.txt File_2.3.txt File_4.7.txt)

for fname in ${filenames[@]}
do
    for seq in {1..999}      # No idea what the upper limit should be
    do
        #if [[ $fname == *$seq* ]]
        # Edit: to handle multi-character sequences
        if [[ $fname == *[_.]$seq.* ]] 
        then
            dir=$(make_dir $seq)
            cp "$fname" "$dir"
        fi
    done
done

Others will no doubt improve on this.

EDITs to the function and the sequence.