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
- The
extglob
argument toshopt -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 toshopt -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.
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