This will find and rename all "*.pdf" files in the current directory whose names follow the
pattern described in the question to the same name but with number
padded to 2 digits:
#!/usr/bin/env bash
shopt -s nullglob
for f in *[[:space:]][0-9].pdf; do
int="$(basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1)"
name="$(basename "$f" | rev | cut -d ' ' -f2- | rev)"
padded_int="$(printf "%02d\n" "$int")"
echo mv "$f" "$(printf "%s %s.pdf" "$name" "$padded_int")"
done
Remove echo before mv to actually run mv but first run it as is
to make sure that it does what you want it to do. Example usage with
the above script saved to pdf.sh:
$ for i in {1..10}; do touch "C Block Scan copy $i.pdf"; done
$ ./pdf.sh
mv C Block Scan copy 1.pdf C Block Scan copy 01.pdf
mv C Block Scan copy 2.pdf C Block Scan copy 02.pdf
mv C Block Scan copy 3.pdf C Block Scan copy 03.pdf
mv C Block Scan copy 4.pdf C Block Scan copy 04.pdf
mv C Block Scan copy 5.pdf C Block Scan copy 05.pdf
mv C Block Scan copy 6.pdf C Block Scan copy 06.pdf
mv C Block Scan copy 7.pdf C Block Scan copy 07.pdf
mv C Block Scan copy 8.pdf C Block Scan copy 08.pdf
mv C Block Scan copy 9.pdf C Block Scan copy 09.pdf
The first line:
#!/usr/bin/env bash
is a shebang.
Additionally, I use env for its
features.
This line
shopt -s nullglob
sets nullglob shell
option
which is also explained on the linked site:
nullglob
If set, Bash allows filename patterns which match no files to
expand to a null string, rather than themselves.
It's needed to prevent for loop from starting if there are no files
that match the pattern criteria:
for f in *[[:space:]][0-9].pdf; do
*[[:space:]][0-9].pdf is a shell pattern that means look for files
that have names composed of any number of characters followed by a
whitespace followed by a single digit and end with .pdf. Inside the
loop $f will hold a name of the processed .pdf file.
Here
int="$(basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1)"
we use command
substitution
to assign integer part of the given file name to a variable. You can
see what basename does in man basename and reproduce the pipeline
in the terminal:
$ f='C Block Scan copy 1.pdf'
$ echo basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1
1
$ f='C Block Scan copy 5.pdf'
$ echo basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1
5
(Notice that $ here is a command line
prompt
used to indicate start of a new line, not a part of the command).
In the next line
name="$(basename "$f" | rev | cut -d ' ' -f2- | rev)"
we extract name part of the .pdf, that is everything before the
number.
In the next line
padded_int="$(printf "%02d\n" "$int")"
we use Bash built-in printf command to pad $int and save it to a
variable called padded_int. In the last line in the loop
echo mv "$f" "$(printf "%s %s.pdf" "$name" "$padded_int")"
we run (without echo of course) the actual renaming using printf
and command substitution again. printf is used with 2 %s format
specifiers and 2 corresponding arguments, similarly as in C.
The last line
done
closes the loop.
echo $SHELLgives/usr/local/bin/bash)”in your code which is not ASCII double quote but something else.