Convert all file extensions to lower-case
Solution
You can solve the task in one line:
find . -name '*.*' -exec sh -c '
a=$(echo "$0" | sed -r "s/([^.]*)\$/\L\1/");
[ "$a" != "$0" ] && mv "$0" "$a" ' {} \;
Note: this will break for filenames that contain newlines. But bear with me for now.
Example of usage
$ mkdir C; touch 1.TXT a.TXT B.TXT C/D.TXT
$ find .
.
./C
./C/D.TXT
./1.TXT
./a.TXT
./B.TXT
$ find . -name '*.*' -exec sh -c 'a=$(echo "$0" | sed -r "s/([^.]*)\$/\L\1/"); [ "$a" != "$0" ] && mv "$0" "$a" ' {} \;
$ find .
.
./C
./C/D.txt
./a.txt
./B.txt
./1.txt
Explanation
You find all files in current directory (.
) that have period .
in its name (-name '*.*'
) and run the command for each file:
a=$(echo "$0" | sed -r "s/([^.]*)\$/\L\1/");
[ "$a" != "$0" ] && mv "{}" "$a"
That command means: try to convert file extension to lowercase (that makes sed
):
$ echo 1.txt | sed -r "s/([^.]*)\$/\L\1/"
1.txt
$ echo 2.TXT | sed -r "s/([^.]*)\$/\L\1/"
2.txt
and save the result to the a
variable.
If something was changed [ "$a" != "$0" ]
, rename the file mv "$0" "$a"
.
The name of the file being processed ({}
) passed to sh -c
as its additional argument and it is seen inside the command line as $0
.
It makes the script safe, because in this case the shell take {} as a data, not as a code-part, as when it is specified directly in the command line.
(I thank @gniourf_gniourf for pointing me at this really important issue).
As you can see, if you use {}
directly in the script,
it's possible to have
some shell-injections in the filenames, something like:
; rm -rf * ;
In this case the injection will be considered by the shell as a part of
the code and they will be executed.
While-version
Clearer, but a little bit longer, version of the script:
find . -name '*.*' | while IFS= read -r f
do
a=$(echo "$f" | sed -r "s/([^.]*)\$/\L\1/");
[ "$a" != "$f" ] && mv "$f" "$a"
done
This still breaks for filenames containing newlines. To fix this issue, you need to have a find
that supports -print0
(like GNU find
) and Bash (so that read
supports the -d
delimiter switch):
find . -name '*.*' -print0 | while IFS= read -r -d '' f
do
a=$(echo "$f" | sed -r "s/([^.]*)\$/\L\1/");
[ "$a" != "$f" ] && mv "$f" "$a"
done
This still breaks for files that contain trailing newlines (as they will be absorbed by the a=$(...)
subshell. If you really want a foolproof method (and you should!), with a recent version of Bash (Bash≥4.0) that supports the ,,
parameter expansion here's the ultimate solution:
find . -name '*.*' -print0 | while IFS= read -r -d '' f
do
base=${f%.*}
ext=${f##*.}
a=$base.${ext,,}
[ "$a" != "$f" ] && mv -- "$f" "$a"
done
Back to the original solution
Or in one find
go (back to the original solution with some fixes that makes it really foolproof):
find . -name '*.*' -type f -exec bash -c 'base=${0%.*} ext=${0##*.} a=$base.${ext,,}; [ "$a" != "$0" ] && mv -- "$0" "$a"' {} \;
I added -type f
so that only regular files are renamed. Without this, you could still have problems if directory names are renamed before file names. If you also want to rename directories (and links, pipes, etc.) you should use -depth
:
find . -depth -name '*.*' -type f -exec bash -c 'base=${0%.*} ext=${0##*.} a=$base.${ext,,}; [ "$a" != "$0" ] && mv -- "$0" "$a"' {} \;
so that find
performs a depth-first search.
You may argue that it's not efficient to spawn a bash
process for each file found. That's correct, and the previous loop version would then be better.
How do I de-capitalize all file extensions given a directory?
Use the ToLower()
method of the String
class, and the ChangeExtension()
method of the Path
class. This should allow you to lowercase all of the extensions without having to enumerate every possible extension.
DirectoryInfo folder = new DirectoryInfo("c:\whatever");
FileInfo[] files = dirInfo.GetFiles("*.*");
foreach (var file in files)
{
File.Move(file.FullName, Path.ChangeExtension(file,
Path.GetExtension(file).ToLower()));
}
Batch rename extension to lowercase
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%A IN (
'dir /b /a-d "%sourcedir%\*" '
) DO (
FOR /f "delims=" %%a IN (
'dir /b /l "%sourcedir%\%%A" '
) DO (
if "%%~xa" neq "%%~xA" ECHO REN "%sourcedir%\%%A" "%%~nA%%~xa"
)
)
GOTO :EOF
Naturally, the two nested for
commands may be compacted to a single line if desired - shown here on multiple lines for legibility.
You would need to change the setting of sourcedir
to suit your circumstances.
The required REN commands are merely ECHO
ed for testing purposes. After you've verified that the commands are correct, change ECHO REN
to REN
to actually rename the files.
Note that %%A
retains the original character-case but %%a
(a completely different variable) acquires the lower-case equivalent because of the /l
switch on the dir
command.
Following Aacini's response, more extensive testing (well, actually trying to rename files rather than just generate a rename instruction that should on first glance work) revealed this doesn't actually work, possibly because the OS sees a file being renamed to its own name (disregarding case). Hmph.
So - first step was to rename twice - first to a dummy name, and then from the dummy name to the required name.
Fine in theory. Problem was that the ~x
operator doesn't seem to consistently report the same string - almost depending on how many times it's used. So - I tried executing a subroutine, passing the "to" and "from" filenames. The subroutine seemed to have the same problems when attempting to access the name fragments of the parameters. Gloom.
So I assigned the name to a variable and tried processing that. Repeatedly remove the string before .
in the name until there are no more dots and you have the extension.
Then remove the extension from the filename, but can't use the replace-with-nothing method since the filename may be whatever.txt.txt
for instance. So lop off the last few characters one at a time within a loop for the length of the extension found+1 (for the dot).
So - if the lower-case version of the extension found is the same as the current-case version in ext2
, no rename required. Otherwise, rename to the original-case name+the lower-case extension. Via a dummy name to ensure the OS doesn't get too smart for itself.
And here's the result. Subject to unexpected results with the usual characters, of course.
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
:choosedummy
SET "dummyname=dummyname.%random%"
IF EXIST "%sourcedir%\%dummyname%" GOTO choosedummy
FOR /f "delims=" %%A IN (
'dir /b /a-d "%sourcedir%\*" '
) DO (
FOR /f "delims=" %%a IN (
'dir /b /l "%sourcedir%\%%A" '
) DO CALL :casechg "%%a" "%%A"
)
GOTO :EOF
:casechg
SET "ext2=%~2"
SET "name2=%~2"
:ext2loop
IF "%ext2%" neq "%ext2:*.=%" SET "ext2=%ext2:*.=%"&GOTO ext2loop
:: if extension cases are identical, or no extension, skip rename
IF "%~x1" equ "" GOTO :EOF
IF "%~x1" equ ".%ext2%" GOTO :EOF
SET "lop=%ext2%"
:loploop
SET "name2=%name2:~0,-1%"
IF DEFINED lop SET "lop=%lop:~1%"&GOTO loploop
REN "%sourcedir%\%~2" "%dummyname%"
REN "%sourcedir%\%dummyname%" "%name2%%~x1"
GOTO :eof
Most Pythonic and fastest way to change a file name extension, if it's uppercase, to lower case
if you want lowercase all of the extensions, not just 'PDF', or/and have some more control on renaming most simple, intuitive and self-descriptive base of solution is
def lowercase_exts(folder):
for fname in os.listdir(folder):
name, ext = os.path.splitext(fname)
os.rename(os.path.join(folder, fname), os.path.join(folder, name + ext.lower()))
But if you need just efficiently rename millions of pdf on windows
import os
import subprocess
os.chdir(folder)
subprocess.call('ren *.PDF *.pdf', shell=True)
Where in the code can I change file extension to lowercase before uploading?
The proper way to change a file name in Fine Uploader would be to use the setName
API method inside of a submit
event handler.
For example, to ensure all file extensions are lower-case:
var uploader = new qq.FineUploader({
/* other required config options left out for brevity */
callbacks: {
onSubmit: function(id, name) {
var extension = qq.getExtension(name);
if (extension != null) {
var newName = name.replace(new RegExp('\\.' + extension + '$'), extension.toLowerCase());
this.setName(id, newName);
}
}
}
});
File extension is change upper case to lower case in codeigniter
please change CI system library
default in CI upload library $file_ext_tolower = FALSE.
.system\libraries\upload.php
public $file_ext_tolower = TRUE;
How can I change a R script file to a lowercase r file extension?
R can do it the following way:
x <- list.files(pattern = "\\.R$") # make sure to set working directory first
file.rename(x, sub("R$", "r", x))
Android: Convert .extensions to Lower/Upper case
A simple attachemtnDescription.toString().toUpperCase().endsWith(".JPG")
will solve your problem, convert the file name to uppercase/lowercase before do the comparison.
Related Topics
How to Record What Process or Kernel Activity Is Using the Disk in Gnu/Linux
Where Is Hardware Timer Interrupt
Why Is There No Directx API for Linux
How to Emulate the Raspberry Pi 2 on Qemu
Dummy Questions About Setting Up Git on Amazon Cloud Ec2
How to Get the First Column of Comm Output
Allocate Writable Memory in the .Text Section
How to List (Ls) the 5 Last Modified Files in a Directory
Timed Out While Waiting for the MAChine to Boot When Vagrant Up
Exclude List of Files from Find
Postgresql -Bash: Psql: Command Not Found
How to Remove All Special Characters in Linux Text
Centos Error - Sudo: Effective Uid Is Not 0, Is Sudo Installed Setuid Root