LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Script for rename files. (https://www.linuxquestions.org/questions/linux-newbie-8/script-for-rename-files-4175589381/)

hack3rcon 09-14-2016 12:52 AM

Script for rename files.
 
Hello.
I have many files with .MP3 and .mkv suffix but after .MP3 and .mkv they have other characters. For example, guitar.mp3?1234yhh, How can I write a script that rename my files to a correct suffix?

Tnx.

grail 09-14-2016 01:01 AM

What have you tried and where are you stuck? Searching both on this site and google would yield a plethora of results to aid any solution you require.

pan64 09-14-2016 02:38 AM

you do not need script, there is a command rename to do that.

Turbocapitalist 09-14-2016 06:41 AM

Yes, "rename" is what you want, unless you really want to write your own script. Just be sure to use it with the -n option while figuring out the right patterns to use. As far as the patterns go, they are normal perl expressions, so anything perl works. You may have already encountered perl patterns in the form of PCRE.

syg00 09-14-2016 07:03 AM

Depends which "rename" is installed.

Turbocapitalist 09-14-2016 07:10 AM

Quote:

Originally Posted by syg00 (Post 5605085)
Depends which "rename" is installed.

Thanks. I've only encountered the perl-based one. I see now that there is another one but notice upon inspection that it seems weak in comparison.

syg00 09-14-2016 07:13 AM

Tell me about it - bloody annoying actually ... :rolleyes:

keefaz 09-14-2016 07:14 AM

Quote:

Originally Posted by Turbocapitalist (Post 5605086)
Thanks. I've only encountered the perl-based one. I see now that there is another one but notice upon inspection that it seems weak in comparison.

Yes the binary version is just a tool to do quick basic rename. It's still useful to do padding zeros filenames, fix file extension etc

schneidz 09-14-2016 07:50 AM

i would hack around the file command to help print out the file type (maybe the -i argument to have it print out the mime-type).

IsaacKuo 09-14-2016 10:17 AM

Another command which you can use for such tasks is "mmv". To strip off everything after .mp3, you'd use:

Code:

mmv -v "*.mp3*" "#1.mp3"
-v flag means "verbose". This lets you see what it's doing.

"*.mp3*" matches any file with ".mp3" in it, with two wildcards. Those wildcards will get mapped to #1 and #2.

"#1.mp3" means the contents of the first wildcard (#1) plus ".mp3". The contents of the second wildcard (#2) are ignored.

Note that this means there is a possibility of a name collision. But mmv has a built in safety check that will warn you if there is a name collision. If it detects a name collision, it will do nothing to the files.

teckk 09-14-2016 02:01 PM

Lots of ways to do that. To the OP, you have 886 posts. Why haven't you studied even a little bash and regex?

Some examples:
Code:

list="
guitar.mp3?1234yhh
guitar.mkv?1234yhh
house.mp312345
house.mkv54321
"

Code:

for i in $list; do
    if grep -q .mp3 <<< $i; then
        echo ${i%.*}.mp3
    elif
        grep -q .mkv <<< $i; then
        echo ${i%.*}.mkv
    fi
done

OR
Code:

for i in $list; do
    if [[ $i == *".mp3"* ]]; then
        echo ${i%.*}.mp3
    elif
        [[ $i == *".mkv"* ]]; then
        echo ${i%.*}.mkv
    fi
done

OR
Code:

for i in $list; do
    case $i in
        *.mp3*) echo ${i%.*}.mp3
        ;;
   
        *.mkv*) echo ${i%.*}.mkv
        ;;
    esac
done


Sefyir 09-14-2016 02:47 PM

Can do this with parallel

Code:

parallel 'echo {1} {1.}.mp3; echo {2} {2.}.mkv' ::: *mp3* ::: *mkv*

keefaz 09-14-2016 02:48 PM

Perl rename (when rename script not installed :/)
Code:

cd /dir/of/files
perl -e 'map {rename $_, s/(\.m..).+/$1/r} grep {/\.mp3.+|\.mkv.+/} <*>'


keefaz 09-14-2016 02:54 PM

Quote:

Originally Posted by Sefyir (Post 5605268)
Can do this with parallel

Code:

parallel 'echo {1} {1.}.mp3; echo {2} {2.}.mkv' ::: *mp3* ::: *mkv*

Nice, I have to install this :)

pan64 09-15-2016 01:50 AM

and one more solution can be:
Code:

for f in *.mp3*; do
    mv $f ${f%%mp3*}mp3
done
# not tested

(and similar to mkv)

nisagnel 09-15-2016 08:26 AM

Hi ,

You can use the following script. I have tested it. Let me know if it not works for your scenario.
______
#!/bin/bash
cd [mp3/mkv files directory]
for i in `ls -A`
do

real=`echo $i | awk -F '.' '{print $1"."substr($2,RSTART-3,3)}'`
mv $i $real

done
______

Regards,
Agnel

IsaacKuo 09-15-2016 08:48 AM

Warning about any script using "mv": make sure to at least use the flag "-i" with mv. By default, mv will merrily overwrite the target if it already exists, with no warning or even any output telling you that it has done so.

As a result, using "mv" in a script without "-i" is a great way to accidentally squash all of your files except one. Or more troubling, any name collision will result in some lost files, without it being obvious that this has happened.

By including the "-i" flag, a name collision will result in mv interactively asking you whether or not to overwrite. The result will likely be a mess to clean up...some files renamed but others not yet renamed. But that's easily preferable to silent data loss.

keefaz 09-15-2016 08:58 AM

I agree but on this particular case (downloaded mp3 and mkv with added text on extension), I would think it's a safe bet to assume that names are unique (movie title or audio song title). I mean OP issue looks like more a quick fix than a long term repeatable solution

IsaacKuo 09-15-2016 09:52 AM

I would not think it's a safe bet. The example given was "guitar.mp3?1234yhh", which may be a completely made up name, but it might also indicate that some of the mp3 files may be very common names (such as names of files from some sort of download?).

Also, there could be subfolders involved, where a slip up could result in files from different folders going to the same destination folder. Depending on how subtracks are named, that could mean a LOT of name collisions.

keefaz 09-15-2016 11:09 AM

yes, I know you're right. But what if the Op prefers a fast quick n' dirty rename and doesn't mind overwriting files than being asked the same question again and again, I mean he didn't bother naming the files in the first place so what is the importance of guitar.mp3?1234yhh, guitar.mp3 etc

Edit: rewriten perl code to add some uniqueness
Code:

# guitar.mp3?1234yhh => guitar?1234yhh.mp3 etc
cd /dir/of/downloaded/files
perl -e 'map {rename $_, s/(\.m..)(.+)/$2$1/r} grep {/\.mp3.+|\.mkv.+/} <*>'


Turbocapitalist 09-15-2016 02:15 PM

The original is pretty short as it is. It's mostly comments / POD:

Code:

#!/usr/bin/perl -w
#
#  This script was developed by Robin Barker (Robin.Barker@npl.co.uk),
#  from Larry Wall's original script eg/rename from the perl source.
#
#  This script is free software; you can redistribute it and/or modify it
#  under the same terms as Perl itself.
#
# Larry(?)'s RCS header:
#  RCSfile: rename,v  Revision: 4.1  Date: 92/08/07 17:20:30
#
# $RCSfile: rename,v $$Revision: 1.5 $$Date: 1998/12/18 16:16:31 $
#
# $Log: rename,v $
# Revision 1.5  1998/12/18 16:16:31  rmb1
# moved to perl/source
# changed man documentation to POD
#
# Revision 1.4  1997/02/27  17:19:26  rmb1
# corrected usage string
#
# Revision 1.3  1997/02/27  16:39:07  rmb1
# added -v
#
# Revision 1.2  1997/02/27  16:15:40  rmb1
# *** empty log message ***
#
# Revision 1.1  1997/02/27  15:48:51  rmb1
# Initial revision
#

use strict;

use Getopt::Long;
Getopt::Long::Configure('bundling');

my ($verbose, $no_act, $force, $op);

die "Usage: rename [-v] [-n] [-f] perlexpr [filenames]\n"
    unless GetOptions(
        'v|verbose' => \$verbose,
        'n|no-act'  => \$no_act,
        'f|force'  => \$force,
    ) and $op = shift;

$verbose++ if $no_act;

if (!@ARGV) {
    print "reading filenames from STDIN\n" if $verbose;
    @ARGV = <STDIN>;
    chop(@ARGV);
}

for (@ARGV) {
    my $was = $_;
    eval $op;
    die $@ if $@;
    next if $was eq $_; # ignore quietly
    if (-e $_ and !$force)
    {
        warn  "$was not renamed: $_ already exists\n";
    }
    elsif ($no_act or rename $was, $_)
    {
        print "$was renamed as $_\n" if $verbose;
    }
    else
    {
        warn  "Can't rename $was $_: $!\n";
    }
}


__END__

=head1 NAME

rename - renames multiple files

=head1 SYNOPSIS

B<rename> S<[ B<-v> ]> S<[ B<-n> ]> S<[ B<-f> ]> I<perlexpr> S<[ I<files> ]>

=head1 DESCRIPTION

C<rename>
renames the filenames supplied according to the rule specified as the
first argument.
The I<perlexpr>
argument is a Perl expression which is expected to modify the C<$_>
string in Perl for at least some of the filenames specified.
If a given filename is not modified by the expression, it will not be
renamed.
If no filenames are given on the command line, filenames will be read
via standard input.

For example, to rename all files matching C<*.bak> to strip the extension,
you might say

        rename 's/\.bak$//' *.bak

To translate uppercase names to lower, you'd use

        rename 'y/A-Z/a-z/' *

=head1 OPTIONS

=over 8

=item B<-v>, B<--verbose>

Verbose: print names of files successfully renamed.

=item B<-n>, B<--no-act>

No Action: show what files would have been renamed.

=item B<-f>, B<--force>

Force: overwrite existing files.

=back

=head1 ENVIRONMENT

No environment variables are used.

=head1 AUTHOR

Larry Wall

=head1 SEE ALSO

mv(1), perl(1)

=head1 DIAGNOSTICS

If you give an invalid Perl expression you'll get a syntax error.

=head1 BUGS

The original C<rename> did not check for the existence of target filenames,
so had to be used with care.  I hope I've fixed that (Robin Barker).

=cut

Fortunately it is included in many distros and easily added to the others.


All times are GMT -5. The time now is 04:10 AM.