Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

241
Views
How to create a list of subdirectories in a list of directories in bash

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.

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

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
  • The extglob argument to shopt -s enables extended globs in Bash, to support the @(MP4|MOV|AVI|WMV|MKV) pattern. See the extglob section in glob - Greg's Wiki.
  • The nullglob argument to shopt -s causes glob patterns that don't match anything to expand to nothing (instead of (what amounts to) garbage), making them safe to loop over.
  • See Removing part of a string (BashFAQ/100 (How do I do string manipulation in bash?)) for explanations of the string manipulations used to extract the parts of the filename.
over 4 years ago · Santiago Trujillo Report

0

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. And only required files ( room_21_user_x.MP4 room_20_user_x..MP4 room_20_user_x.Mp4 room_20_user_x.MP Room_20_user_x.MP4 room_20_user_x.MP43 etc...)

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
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!