Rename all the files in .ts files in a directory My echo command works but not if I try to make it a new variable.
#!/bin/sh
for file in "${1}"/*.ts; do
echo ${file} | sed -e 's|.ts|.mkv|'
new_name=${file} | sed -e 's|.ts|.mkv|'
done
Rename all the files in .ts files in a directory My echo command works but not if I try to make it a new variable.
#!/bin/sh
for file in "${1}"/*.ts; do
echo ${file} | sed -e 's|.ts|.mkv|'
new_name=${file} | sed -e 's|.ts|.mkv|'
done
The simplest solution would be to tell you to change the assignment to:
new_name=$( echo ${file} | sed -e 's|.ts|.mkv|' )
But a better solution would be to do:
new_name="${file%.ts}.mkv"
"${1}"/*.ts I don't see how a .mkv file gets in the list. @NasKar
–
Jan 29 '19 at 06:28
find . -maxdepth 1 -type f -name '*.ts' -exec rename .ts .mkv {} "+"
Run this in the directory containing the .ts files.
By using $file unquoted in your code, you invite the shell to split its contents into words based on the value of $IFS (space, tab and newline by default). Those words would then undergo filename expansion if they contained any globbing patterns.
By using echo, you would possibly also expand backslash sequences like \n and \t depending on what shell options happened to be set (xpg_echo).
Your first sed command would replace any character followed by ts in the filename with .mkv. This means that the filename bats.ts would be changed to b.mkv.ts.
The second line in the loop is nonsensical, as it takes the output of an assignment and passes it to sed over a pipe.
Assigning the output of a command to a variable is done with command substitutions:
variable=$( some_command )
#!/bin/sh
for name in "$1"/*.ts; do
mv -i "$name" "${name%.ts}.mkv"
done
This would loop over all files having a filename suffix of .ts in the directory given by "$1". Each file would be renamed to the same name, but with the .ts filename suffix removed and the .mkv suffix inserted at the end of the filename.
The variable substitution ${variable%pattern} would remove the shortest suffix in $variable that matches pattern. This would work even if the filename happened to contain embedded newlines.
By using mv -i we hopefully prevent the function from accidentally overwriting existing files. Another way to do that would be to do something like
#!/bin/sh
for name in "$1"/*.ts; do
newname=${name%.ts}.mkv
if [ ! -e "$newname" ]; then
mv "$name" "$newname"
else
printf 'Name "%s" is already taken\n' "$newname" >&2
fi
done
In addition to this test, you may actually want to check whether $name exists to start with. If the pattern "$1"/.*ts does not match any filenames, then it would by default remain unexpanded. We can catch that with
#!/bin/sh
for name in "$1"/*.ts; do
[ ! -e "$name" ] && break
newname=${name%.ts}.mkv
if [ ! -e "$newname" ]; then
mv "$name" "$newname"
else
printf 'Name "%s" is already taken\n' "$newname" >&2
fi
done
In the bash shell, you could use shopt -s nullglob to make nonmatching patterns expand to nothing instead. In bash you may also want to use shopt -s dotglob if you want to additionally match hidden filenames.
#!/bin/sh
for file in "${1}"/*.ts; do
mv "${file}" "$(basename "${file}").mkv"
done
basename to remove the .ts suffix, you will need to specify that with an option and provide the suffix to remove explicitly (at least in those implementations of basename I have come across so far).
– AdminBee
Sep 23 '21 at 08:29
mv target, so the new files will end up in the current directory.
– Stephen Kitt
Sep 23 '21 at 11:25
rename. If the Perl version, it's justrename 's/.ts$/.mkv' *. – Sparhawk Jan 28 '19 at 01:38.tsactually Matroska files? Why are they all misnamed? – jamesdlin Jan 28 '19 at 05:57