How do I call a script with a wildcard pattern and two more arguments?
You call your script with
./script file_*.jpg jpg bak
But *
gets expanded before it is passed to the script. Assuming you have the files file_1.jpg
, file_2.jpg
and file_3.jpg
in your folder, this is what is invoked:
./script file_1.jpg file_2.jpg file_3.jpg jpg bak
which means that ${1} = file_1.jpg
, ${2} = file_2.jpg
and ${3} = file_3.jpg
.
It might be better if you write your script such, that (in your example): ${1} = jpg
and ${2} = bak
. Then you can store those variables in your script, invoke shift 2
to get rid of them, and loop over all positional arguments simply by using
for file; do
# do something
done
Related videos on Youtube
OMA
Updated on September 18, 2022Comments
-
OMA over 1 year
I have this code to rename a bunch of files:
#!/bin/bash for file in $1 do mv -i "${file}" "${file/pattern/replacement}" done
How do I replace "pattern" and "replacement" with $2 and $3?
This code does not work:
#!/bin/bash for file in $1 do mv -i "${file}" "${file/$2/$3}" done
I'm trying to rename using the following 3 arguments:
file_*.jpg jpg bak
(the result should be renaming all*.jpg
files to*.bak
files). But all it does is:mv -i file_01.jpg file_01.jpg
(thus not renaming anything, since both mv arguments are identical, plus it stops at the first file, even when there are more*.jpg
files). If I manually typejpg
andbak
into the bash script instead of$2
and$3
then it DOES work.-
Ipor Sircer over 7 yearsIt works for me.
-
pfnuesel over 7 yearsHow do you invoke that script?
-
pfnuesel over 7 yearsMaybe add
#!/usr/bin/env bash
on top of the script, to make sure bash is invoked. -
Арсений Черенков over 7 yearsIt looks like you are rewriting rename command ...
-
OMA over 7 years@Archemar: What rename command? Excuse my ignorance, but I don't know any rename command other than "mv"
-
Арсений Черенков over 7 yearssee
man rename
-
OMA over 7 yearsThat command is not available for me. That's why I asked.
-
-
Stéphane Chazelas over 7 yearsAs written, the script would work if called as
./script 'file_*.jpg' jpg bak
as$1
is unquoted, so subject to split+glob, so thatfile_*.jpg
would be expanded at that point. Your advice of having $1=pat, $2=ret and the rest the list of files is certainly best though (1- to avoid having to quote the pattern, 2- to avoid confusing users of other shells with different globs than bash, 3- to allow patterns likemy file*
...) -
Stéphane Chazelas over 7 yearsconsider using
getopts
to process your options. For instance, had you usedgetopts
, you would have been able to domyscript -- -p -q files
to replace-p
with-q
, and-ppp
would have meant the same as-p
. -
Stéphane Chazelas over 7 yearsYour use of needle, haystack and wildcard words is confusing here.
-
Stéphane Chazelas over 7 yearsNote that if your boolean variables are made to contain only
true
orfalse
, you can just doif "$found"
instead ofif [ "$found" = true ]
. -
Stéphane Chazelas over 7 yearsNote that
[ -f "$file" ]
is not for file existence, but that the file exists and is a regular file (or symlink to regular file). That would exclude all other types of file like fifo, device, directory... -
OMA over 7 yearsThanks a lot for reviewing my code and for all your comments, Stéphane! You're really helpful! I've implemented most of your suggestions, except getopts (I have to learn more about it) and
if [ "$found" ]
, because that results in true when $found contains "false" (it's a string after all; I used strings since booleans don't exist in Bash). Also I don't mind theif [ -f "$file" ]
checking only for regular files. It's all I need for now. -
OMA over 7 yearsBTW, it seems I'm reinventing the wheel here since there is an actual "rename" command I didn't know about the existence of, but it's not available on my machine, so my script will do. Plus, it's a nice exercise in Bash scripting :)
-
Stéphane Chazelas over 7 yearsyes, rename (both util-linux, perl's and now separate perl script with more extensions) and also
mmv
and zsh'szmv
... -
Stéphane Chazelas over 7 yearsNote that I said
if "$found"
, notif [ "$found" ]
, as in run the command stored in$found
(false
andtrue
being builtin bash commands), not the[
command with the content of$found
as argument. -
OMA over 7 yearsAh, I see. That's another intricacy I didn't know about :). About "mmv" and "zmv", those aren't available here, either
-
Stéphane Chazelas over 7 years
zmv
is a function shipped withzsh
, so you can use all the expansion operators and glob operators ofzsh
(useautoload zmv
from withinzsh
to enable it). You can search this site forzmv
to see hundreds of examples.