How can I rename directories from “[YYYY] Title” or “(YYYY) Title” to “YYYY – Title”?

0
0
Asked By MellowCedar42 On

I have a directory containing several subdirectories whose names begin with a four-digit year. Each name follows either "[YYYY] Title" or "(YYYY) Title", and I want to rename them to "YYYY - Title". I'm still learning Bash and was considering looping over the directories, extracting the year with a regular expression, and then using mv to apply the new name. What's a safe and reasonably simple way to do this?

3 Answers

Answered By QuietHarbor7 On

You can do this entirely in Bash with a pattern loop and parameter expansion. This version only considers directories, handles both bracket styles, prints each change first, and avoids overwriting an existing destination:

```bash
for d in ([0-9][0-9][0-9][0-9]) * [[0-9][0-9][0-9][0-9]] *; do
[ -d "$d" ] || continue

year="${d:1:4}"
title="${d:7}"
new="${year} - ${title}"

if [ -e "$new" ]; then
printf 'Skipping: destination already exists: %sn' "$new" >&2
continue
fi

printf 'Would rename: %q -> %qn' "$d" "$new"
# mv -- "$d" "$new"
done
```

Once the output looks right, uncomment the `mv` line. Keeping the old name and new name quoted is important because titles may contain spaces or shell characters.

BrightPanda18 -

The `[ -d "$d" ]` check is useful here because the glob can also remain literal when nothing matches, and it prevents accidentally processing regular files.

Answered By SilverMaple26 On

For a small number of directories, an interactive tool such as `vidir` can be less error-prone. It opens a listing in your editor; you change the names in the listing and save it, and the tool performs the corresponding renames. That gives you a chance to review every change without writing a script.

Answered By CopperWren53 On

If you prefer regular expressions, Bash stores captured groups in `BASH_REMATCH`. This matches either kind of opening and closing bracket and captures the year and title:

```bash
for d in */; do
d=${d%/}

if [[ $d =~ ^[([0-9]{4})] (.*)$ || $d =~ ^(([0-9]{4})) (.*)$ ]]; then
year=${BASH_REMATCH[1]}
title=${BASH_REMATCH[2]}
new="$year - $title"

printf '%q -> %qn' "$d" "$new"
# mv -- "$d" "$new"
fi
done
```

The `*/` glob limits the loop to entries that look like directories, and removing the trailing slash makes the string easier to work with. Test with `printf` before enabling `mv`, especially if two source directories could produce the same destination name.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.