Home > Blockchain >  How to create a list of subdirectories in a list of directories in bash
How to create a list of subdirectories in a list of directories in bash

Time:03-11

First of all, I'm not allowed to use more for or while loops because this is task for university.

I have the following:

for i in {00..20}
do  
    users=( $(ls "$dir"/"$1" | grep "room_${i}_*" | cut -d '.' -f 1 | cut -d '_' -f 3-4 | sort | uniq) )
    cd "$dir"/"$2"/r"${i}" || exit
    mkdir -p "${users[@]}"/{MP4,MOV,AVI,WMV,MKV}
done

I have bunch of videos named room_XX_user_Y.ext, where XX is a number between 00 and 20, Y is unknown and ext is one of {MP4,MOV,AVI,WMV,MKV}. So, I have to move the file to /rXX/user_Y/ext/ and I have to create all of them except rXX (r stands for room). Every user has a video with this extensions.

I'm able to do everything except creating all the {MP4,MOV,AVI,WMV,MKV} directories inside the user_Y directory. If the users for a room are a, b, c and d, the directories for extensions will only be created on the user_d directory.

Thank you all.

CodePudding user response:

Try this Shellcheck-clean code:

#! /bin/bash -p

srcdir=$1
destdir=$2

shopt -s extglob nullglob
for video_path in "$srcdir"/room_[0-9][0-9]_user_*.@(MP4|MOV|AVI|WMV|MKV); do
    room_xx_user_y_ext=${video_path##*/}
    ext=${room_xx_user_y_ext##*.}
    room_xx_user_y=${room_xx_user_y_ext%.*}
    xx_user_y=${room_xx_user_y#room_}
    xx=${xx_user_y%%_*}
    user_y=${xx_user_y#*_}

    video_destdir="$destdir/r${xx}/${user_y}/${ext}"
    mkdir -pv -- "$video_destdir"
    mv -iv -- "$video_path" "$video_destdir"
done

CodePudding user response:

Suggesting the following solution:

1. Locate all the files with find command.

find . -regextype egrep -regex "^room_([01][0-9]|20)_user_[^\.] \.(MP4|MOV|AVI|WMV|MKV)"

Improve this command till you locate all designated files.

2. Dissect each file name to its compoents

for currFile in $(find . -regextype egrep -regex "^room_([01][0-9]|20)_user_[^\.] \.(MP4|MOV|AVI|WMV|MKV)"); do 
   currFileName=$(basename $currFile)
   xx=${currFileName:5:2}
   y=${currFileName:13}
   y=${y::-4}
   ext=${currFileName:(-3):3}
   printf "xx=%s y=%s ext=%s\n" $xx $y $ext
done

Improve the string dissection to perfection.

3. Rebuild destination path

for currFile in $(find . -regextype egrep -regex "^room_([01][0-9]|20)_user_[[:alpha:]]\.(MP4|MOV|AVI|WMV|MKV)"); do 
   currFileName=$(basename $currFile)
   xx=${currFileName:5:2}
   y=${currFileName:13}
   y=${y::-4}
   ext=${currFileName:(-3):3}
   destinationPath="/r${xx}/user_${y}/${ext}}"
   echo "destinationPath=$destinationPath"       
done

Make sure destination path is correct for each file.

4. Build the destination file, and relocate the file there

for currFile in $(find . -regextype egrep -regex "^room_([01][0-9]|20)_user_[[:alpha:]]\.(MP4|MOV|AVI|WMV|MKV)"); do 
   currFileName=$(basename $currFile)
   xx=${currFileName:5:2}
   y=${currFileName:13}
   y=${y::-4}
   ext=${currFileName:(-3):3}
   destinationPath="/r${xx}/user_${y}/${ext}}"
   mkdir -p "$destinationPath"    
   mv currFile "$destinationPath" 
done

Do be bothered with the creation of `/r${xx}`. 

Because mkdir -p creates only directories missing in the argument path. mkdir -p ignore existing paths as stated here. Therefore it is safe to use mkdir -p again on existing paths.

If you care to check that /r${xx} is writable directory before assigning it to mkdir -p

if [[ -d "/r${xx}" && -w "/r${xx}" ]]; then
   mkdir -p "$destinationPath"    
   mv currFile "$destinationPath" 
fi
  • Related