2

Given that i have folder that contain 170+ files that were named like 'SM-RVT70UQTNWC02.png'$'\r' how can I fast change this to SM-RVT70UQTNWC02.png? I have tried to apply solution from this question however i'm struggling how to make my regex '*(.*)'\$'\\r' work with rename as I get many errors like:

Scalar found where operator expected at (eval 8) line 1, near "*)$\"
        (Missing operator before $\?)
Backslash found where operator expected at (eval 8) line 1, near "$\\"
        (Missing operator before \?)
syntax error at (user-supplied code), near "*)$\"
Niviral
  • 123
  • I believe you should put the $ first $'s/(.*)\r$/$1/' the second is just for matching line end –  Dec 16 '20 at 07:34
  • 1
    due to the number of files, you can use rename in combination with find: find . -type f -print0 | rename -0 -d $'s/(.*)\r$/$1/' –  Dec 16 '20 at 07:46
  • 1
    It worked. I still don't understand what happen there, but it worked. – Niviral Dec 16 '20 at 07:48

2 Answers2

2

Assuming you listed the file with ls, the quotes are not part of the file name, they are used to help understanding weird file names. The file in question is the concatenation of SM-RVT70UQTNWC02.png and a carriage return (the byte 0x0D), which in Bash can be represented by $'\r' (see ANSI quoting).

To remove the trailing carriage return character of the .png files in the current directory,

rename 's/\r$//' *.png?

The syntax means: substitute the carriage return \r at the end of the line $ by nothing.

A POSIX compliant alternative would be

for f in *.png"$(printf '\r')"; do mv -- "$f" "${f%?}"; done

Printf is the portable way to specify a carriage return, and ${f%?} removes the last character of the file name.

Quasímodo
  • 2,017
1

In that folder run:

for i in *.png*; do
    mv -i "${i}" "${i%.png*}.png"
done

as a one-liner, this becomes

for i in *.png*; do mv -i "${i}" "${i%.png*}.png"; done

This loops over all the files matching *.png* in the current directory and renames (moves) them by cutting off everything starting at the last occurence of .png and then appending .png again. Using %% instead would start cutting off from the first occurence of .png. You can drop the -i if you don't want to confirm overwriting existing files.

Simon
  • 41
  • 2
  • 1
    A more selective solution would be for i in *.png?; do mv -i "${i}" "${i%?}"; done, althought it would still rename non carriage return files (e.g. a.pngx to a.png). – Quasímodo Dec 16 '20 at 09:02