rename -n 'if (-f $_) {
my $c=substr($_,7,1);
if ($c) {
mkdir $c unless (-d $c);
$_="$c/$_" if (-d $c);
};
}' *.ext
This uses the perl rename
command (also known as prename
and file-rename
), NOT to be confused with the rename
command from util-linux
which has completely different and incompatible command line options.
The script iterates over all files on the command line (or read from STDIN) and if the current file is a regular file (i.e. not a directory, named pipe, socket, etc) then it:
- extracts the 8th character using the
substr()
function into variable $c. substr offsets start from 0, so the ,7,1
refers to the 8th character.
- if
$c
isn't empty (which will happen with short filenames), it:
- makes the directory
$c
if it doesn't exist.
- renames the current file into that directory if it is a directory (i.e. doesn't break if
$c
already exists but isn't a directory)
Alternatively, the script could move files into a directory called, e.g., Misc
if $c is empty:
rename -n 'if (-f $_) {
my $c=substr($_,7,1);
$c="Misc" unless ($c);
mkdir $c unless (-d $c);
$_="$c/$_" if (-d $c);
}' *.ext
Note: both examples above use rename
's dry-run option (-n
). They will only show what the files would be renamed/mv-ed to if you let it. When you're satisfied that the rename scrript will do what you want, remove the -n
option (or replace it with -v
for verbose output).
e.g.
$ rename -v 'if (-f $_) { my $c=substr($_,7,1); $c="Misc" unless ($c) ; mkdir $c unless (-d $c); $_="$c/$_" if (-d $c)}' *
9323 - Unix.ext renamed as U/9323 - Unix.ext
foo.ext renamed as Misc/foo.ext
z223 - 50 Cent.ext renamed as 5/z223 - 50 Cent.ext