简体   繁体   中英

UNIX :: Padding for files containing string and multipleNumber

I have many files not having consistent filenames.

For example

IMG_20200823_1.jpg
IMG_20200823_10.jpg
IMG_20200823_12.jpg
IMG_20200823_9.jpg

I would like to rename all of them and ensure they all follow same naming convention

IMG_20200823_0001.jpg
IMG_20200823_0010.jpg
IMG_20200823_0012.jpg
IMG_20200823_0009.jpg

Found out it's possible to change for file having only a number using below

printf "%04d\n" 

However am not able to do with my files considering they mix string + "_" + different numbers.

Could anyone help me ? Thanks !

With Bash regular expressions:

re='(IMG_[[:digit:]]+)_([[:digit:]]+)'

for f in *.jpg; do
    [[ $f =~ $re ]]
    mv "$f" "$(printf '%s_%04d.jpg' "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}")"
done

where BASH_REMATCH is an array containing the capture groups of the regular expression. At index 0 is the whole match; index 1 contains IMG_ and the first group of digits; index 2 contains the second group of digits. The printf command is used to format the second group with zero padding, four digits wide.

With Perl's standalone rename or prename command:

rename -n 's/(\d+)(\.jpg$)/sprintf("%04d%s",$1,$2)/e' *.jpg

Output:

rename(IMG_20200823_10.jpg, IMG_20200823_0010.jpg)
rename(IMG_20200823_12.jpg, IMG_20200823_0012.jpg)
rename(IMG_20200823_1.jpg, IMG_20200823_0001.jpg)
rename(IMG_20200823_9.jpg, IMG_20200823_0009.jpg)

if everything looks fine, remove -n .

Use a regex to extract the relevant sub-strings from the input and then pad it...

  1. For each file.
  2. Extract the prefix, number and suffix from the filename.
  3. Pad the number with zeros.
  4. Create the new filename.
  5. Move files

The following code for bash:

echo 'IMG_20200823_1.jpg
IMG_20200823_10.jpg
IMG_20200823_12.jpg
IMG_20200823_9.jpg' | 
while IFS= read -r file; do  # foreach file
    # Use GNU sed to extract parts on separate lines
    tmp=$(<<<"$file" sed 's/\(.*_\)\([0-9]*\)\(\..*\)/\1\n\2\n\3\n/')
    # Read the separate parts separated by newlines
    {
       IFS= read -r prefix
       IFS= read -r number
       IFS= read -r suffix
    } <<<"$tmp"
    # create new filename
    newfilename="$prefix$(printf "%04d" "$number")$suffix"
    # move the files
    echo mv "$file" "$newfilename"
done

outputs:

mv IMG_20200823_1.jpg IMG_20200823_0001.jpg
mv IMG_20200823_10.jpg IMG_20200823_0010.jpg
mv IMG_20200823_12.jpg IMG_20200823_0012.jpg
mv IMG_20200823_9.jpg IMG_20200823_0009.jpg

Being puzzled by your hint at printf...

Current folder content:

$ ls -1 IMG_*
IMG_20200823_1.jpg
IMG_20200823_21.jpg

Surely is not a good solution but with printf and sed we can do that:

$ printf "mv %3s_%8s_%d.%3s %3s_%8s_%04d.%3s\n" $(ls -1 IMG_* IMG_* | sed 's/_/ /g; s/\./ /')
mv IMG_20200823_1.jpg IMG_20200823_0001.jpg
mv IMG_20200823_21.jpg IMG_20200823_0021.jpg

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM