patternbashMinor
Bash script to rename subfolder to include name of parent folder
Viewed 0 times
scriptincludeparentsubfoldernamefolderbashrename
Problem
Here's the current structure of my directory.
I want to rename the Season folders to include the name of the Show. The desired structure looks like this :
Here's the script I wrote :
This is my first time scripting in Bash. Is there any thing I could improve ?
.
├── Show 1
│ ├── Season 1
│ └── Season 2
├── Show 2
├── Season 1
└── Season 2
I want to rename the Season folders to include the name of the Show. The desired structure looks like this :
.
├── Show 1
│ ├── Show 1 - Season 1
│ └── Show 1 - Season 2
├── Show 2
├── Show 2 - Season 1
└── Show 2 - Season 2
Here's the script I wrote :
# Parse through all show folders.
for show in /Users/sanjeetsuhag/Desktop/* ; do
# Check if it is a folder.
if [ -d "$show" ]; then
# Parse through all season folders.
for season in $show/* ; do
# Check if it is a folder.
if [ -d "$season" ]; then
mv $season "$show/$(basename "$show") - $(basename "$season")"
fi
done
fi
done
This is my first time scripting in Bash. Is there any thing I could improve ?
Solution
You should always double-quote variables that are used as filesystem paths.
This is the same script but with variables correctly double-quoted:
If you change the globs to end with
they will match only directories,
and so you can skip the directory checks:
You could further optimize this by using pattern substitution instead of
The
and the
Finally, instead of hardcoding the base path
the script would be more reusable if you make that a command line parameter of the script.
This is the same script but with variables correctly double-quoted:
# Parse through all show folders.
for show in /Users/sanjeetsuhag/Desktop/*; do
# Check if it is a folder.
if [ -d "$show" ]; then
# Parse through all season folders.
for season in "$show"/*; do
# Check if it is a folder.
if [ -d "$season" ]; then
mv "$season" "$show/$(basename "$show") - $(basename "$season")"
fi
done
fi
doneIf you change the globs to end with
/,they will match only directories,
and so you can skip the directory checks:
for show in /Users/sanjeetsuhag/Desktop/*/; do
for season in "$show"/*/; do
mv "$season" "$show/$(basename "$show") - $(basename "$season")"
done
doneYou could further optimize this by using pattern substitution instead of
basename:for show in /Users/sanjeetsuhag/Desktop/*/; do
for season in "$show"/*/; do
show=${show%/}
season=${season%/}
mv "$season" "$show/${show##*/} - ${season##*/}"
done
doneThe
${show%/} is to shave off the trailing /,and the
${show##*/} is to delete everything until the last /.Finally, instead of hardcoding the base path
/Users/sanjeetsuhag/Desktop,the script would be more reusable if you make that a command line parameter of the script.
Code Snippets
# Parse through all show folders.
for show in /Users/sanjeetsuhag/Desktop/*; do
# Check if it is a folder.
if [ -d "$show" ]; then
# Parse through all season folders.
for season in "$show"/*; do
# Check if it is a folder.
if [ -d "$season" ]; then
mv "$season" "$show/$(basename "$show") - $(basename "$season")"
fi
done
fi
donefor show in /Users/sanjeetsuhag/Desktop/*/; do
for season in "$show"/*/; do
mv "$season" "$show/$(basename "$show") - $(basename "$season")"
done
donefor show in /Users/sanjeetsuhag/Desktop/*/; do
for season in "$show"/*/; do
show=${show%/}
season=${season%/}
mv "$season" "$show/${show##*/} - ${season##*/}"
done
doneContext
StackExchange Code Review Q#151399, answer score: 3
Revisions (0)
No revisions yet.