So I have a script that adds 2 films together using the audio from the $1.audio
file. What I would like to do is rename any file in the directory with:
*.mp4
To:
*.audio
Keeping original file name.
So I have a script that adds 2 films together using the audio from the $1.audio
file. What I would like to do is rename any file in the directory with:
*.mp4
To:
*.audio
Keeping original file name.
You can use the rename
command. It's not portable, but it exists in different forms in different distributions.
In CentOS/RHEL and probably Fedora:
rename .mp4 .audio *.mp4
Should do it. From man rename
on CentOS 6:
SYNOPSIS
rename from to file...
rename -V
DESCRIPTION
rename will rename the specified files by replacing the first occur-
rence of from in their name by to.
In Ubuntu and probably any Debian variant:
rename 's/\.mp4$/.audio/' *.mp4
should do it. From man rename
on Ubuntu 14.04:
SYNOPSIS
rename [ -v ] [ -n ] [ -f ] perlexpr [ files ]
DESCRIPTION
"rename" renames the filenames supplied according to the rule specified
as the first argument. The perlexpr argument is a Perl expression
which is expected to modify the $_ 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 "*.bak" to strip the
extension, you might say
rename 's/\.bak$//' *.bak
Here is a fast and portable solution still handling oddly named files :
find . -name "*.mp4" -exec sh -c 'for i do mv -- "$i" "${i%.mp4}.audio"; done' sh {} +
rename
is definitely more readable.
– Wildcard
Oct 28 '15 at 08:10
Use this for
loop:
for f in *; do
[ -f "$f" ] && mv -v -- "$f" "${f%.mp3}.audio"
done
for i in *
loops trough all files and directories (except dot-files) in the current working directory and stores the current processed file in $f
[ -f "$f" ]
checks if it's a regular filemv -v
renames the file (--
is that the filenames will not be interpreted as arguments by mistake)${f%.mp3}.audio
removes the .mp3
extension and adds the .audio
extension (Parameter Expansion)rename
.
– Wildcard
Nov 27 '15 at 08:07
Here is a solution that uses find
, sed
, and xargs
. This solution works even if there are spaces in the name.
It first gets the files using find
. Then, gets the base name of the file using sed
. Finally, it does the move to change the extension.
Note the code below is multi-line for clarity. You should probably execute it in one line.
# split into three lines for clarity
# should execute as one line
find . -maxdepth 1 -name '*.mp4'
| sed -r 's/.*\/([^/]+)\.mp4/\1/g'
| xargs -ix mv "x.mp4" "x.audio"
Below is an alternative solution using basename
. This solution may work with names containing spaces (have not tested this one).
It first gets all the files with .mp4
extension, then gets the base name, and finally renames each with the audio extension.
# split into three lines for clarity
# should execute as one line
find . -maxdepth 1 -name '*.mp4' -print0
| xargs -0 -ix basename "x" .mp4
| xargs -ix mv "x.mp4" "x.audio"
You can use
for file in `ls *.mp4`; { mv $file `echo $file | sed 's/.mp4/.audio/g'`; }
ls
.
– Wildcard
Oct 27 '15 at 05:01
for
-loop construct is that? It doesn't work in dash
, but works in bash
and zsh
. I vaguely remember seeing this syntax before, but it's been literally decades ago. Is it a ksh
thing? It's really kind of neat, substitute {
for do
, and }
for done
.
– RobertL
Oct 27 '15 at 06:08
rename
differs widely from distribution to distribution even for simple use cases, so I said it's "not portable".find
, on the other hand (see jilliagre's answer), is very portable as it will work in any Linux distribution you're likely to ever encounter. – Wildcard Oct 28 '15 at 04:53