2

I have 13 filenames and i want to pass them as argument in sh

File is like:

$FILEPATTERN = "XYZ_"

FILENAME1="$FILEPATTERN${somedate1}_{sometime}.csv"
FILENAME2="$FILEPATTERN${somedate2}_{sometime}.csv"
FILENAME3="$FILEPATTERN${somedate3}_{sometime}.csv"
...
FILENAME13="$FILEPATTERN${somedate13}_{sometime}.csv"

for g in 1 2 3 4 5 6 7 8 9 10 11 12 13
do
  filenewname=FILENAME${g}
  sh $SCRIPTS/$SCRIPTNAME $filenewname
  filenewname=""
done

when i echo the filenewname, it is printing FILENAME1, FILENAME2....

Expected output should be value inside variable FILENAME1 i.e $FILEPATTERN${somedate1}_{sometime}.csv

codeforester
  • 39,467
  • 16
  • 112
  • 140
Guneet
  • 35
  • 2
  • 9

3 Answers3

4

You need ${!var} construct to access the indirect shell variable. So, rewrite the loop as:

for g in 1 2 3 4 5 6 7 8 9 10 11 12 13
do
  filenewname="FILENAME${g}"
  sh "$SCRIPTS/$SCRIPTNAME" "${!filenewname}"
done

Or, more simply:

for g in {1..13}; do
  filenewname="FILENAME$g"
  sh "$SCRIPTS/$SCRIPTNAME" "${!filenewname}"
done

I have added double quotes around the variables to prevent word splitting and globbing.

As an aside, your first line has a problem - $FILEPATTERN = "XYZ_" is not a valid assignment. It should be FILEPATTERN="XYZ_" (note: no spaces around =). Check your script at shellcheck.


Using all caps for normal shell variables isn't a good practice. See this post for some useful info regarding naming convention:

Community
  • 1
  • 1
codeforester
  • 39,467
  • 16
  • 112
  • 140
0

Use eval. Eval expands it's arguments before executing them and is the standard way in shell scripts to do what you want.

$ FILEPATTERN=XYZ_
$ somedate1=20170515
$ FILENAME1="$FILEPATTERN${somedate1}_{sometime}.csv"
$ eval filenewname=$FILENAME1
$ echo $filenewname
XYZ_20170515_{sometime}.csv
$ 
tk421
  • 5,775
  • 6
  • 23
  • 34
  • [BashFAQ #48: `eval` command and security issues](http://mywiki.wooledge.org/BashFAQ/048) should be required reading for anyone considering this approach. `eval` is POSIX-standardized, yes, but the reasons for extended shells to offer alternatives are compelling -- **especially** in this specific case, where you're letting the value to be assigned be expanded *before* `eval` takes over; it's safer to only expand the destination variable name, not the value. – Charles Duffy May 07 '18 at 15:57
-1

My first time trying to answer a question, but why not use an array for your file names?

#Make an array called 'arr' with 13 strings of our file names 
FILEPATTERN="XYZ_"
arr=(`for i in {1..13}; do echo "$FILEPATTERN${somedate}$i_${sometime}";done`)

I don't know where you're getting ${somedate} and ${sometime} but if the only difference between each of the 13 files is the number at the end, you can pre-generate the filenames like shown above.

#Now loop through that array and perform operations
for name in "${arr[@]}"; do
    echo "Handling $name..."
    sh $SCRIPTS/$SCRIPTNAME $name
done

If this helps, you could also just do it on the fly:

FILEPATTERN="XYZ_"
for i in {1..13}; do
    echo "Handling $name..."
    sh $SCRIPTS/$SCRIPTNAME $FILEPATTERN${somedate}"$i"_${sometime}
done
  • Using string-splitting to split a command substitution's output into an array has some *really* unfortunate side effects. Much better to directly assign: `for ((i=1; i<=13; i++)); do arr[$i]="$FILEPATTERN${somedate}${i}_${sometime}"; done`. And quote your dereferences (as http://shellcheck.net/ would tell you): `"${arr[@]}"`, with the quotes; `"$name"`, with the quotes; etc. And `${i}` needs the curly braces when it's followed by an underscore, or else the shell tries to expand `$i_`, which is a different variable than the one you're setting. – Charles Duffy May 16 '17 at 03:26
  • Thanks for the corrections, I didn't realize $i_ wouldn't be interpreted correctly. With regard to string-splitting in command substitution, I've found whitespace to be reliable enough to make simple lists of words like is desired here, but then I haven't been a sysadmin for very long either so take that for what it's worth. – jesus_is_a_lie May 16 '17 at 03:40
  • The issue with making a habit of relying on practices that work most of the time is that sometimes they don't. For instance, it's easy to forget that when you get string-splitting, you also get glob expansion. One of my war stories is about a time someone made such an assumption, and got a filename (due to a bug in a C module loaded into a Python interpreter dumping random garbage into memory) containing a whitespace-surrounded `*`. Script tries to delete that file; script deletes multiple TB of backups used to support customer billing. – Charles Duffy May 16 '17 at 03:43
  • The other thing is that if you only do the Right Thing when you *think* it's important, then you're missing the times when that decision is wrong. (Or maybe it's right *at the time*, but your code later gets reused in a different scenario -- in the case I gave above, files had always been written by a Java app, before the Python-based tool using the buggy C module was introduced). If you do the right thing every time, and make a habit of it, then you avoid the risk... and will do the right thing *by habit*, even at 3am. – Charles Duffy May 16 '17 at 03:47
  • Wow! Yeah that would be pretty bad. Although anything dumping random garbage in to memory would be Really Bad; whether your variables are written explicitly or not. – jesus_is_a_lie May 16 '17 at 03:49
  • Sure -- but initially, the garbage had been limited to the Python interpreter's own memory; it was only after that Python process created a garbage filename and the inadequately-quoting shell script string-split and glob-expanded that filename and `rm`'d the results of that expansion that things turned into an outright disaster (and files written by the other, non-Python, non-corrupt producers were deleted as well). – Charles Duffy May 16 '17 at 03:51
  • (Cascades of problems -- ie. one thing leading to another -- is also how a lot of security breaches tend to happen: Someone gets a toehold, and then tries to figure out how to leverage that toehold into a larger breach. While this is getting beyond the string-splitting-and-globbing discussion previously at hand, being paranoid as a matter of habit means that someone who's figured out how to, say, create arbitrary files in some random directory can't also use a shell injection attack to run a command by embedding it in a filename). – Charles Duffy May 16 '17 at 04:01
  • (that said, that's only *kinda* out-of-scope -- let's say that an attacker figured out how to make `SCRIPTS='-c mydir/myscript'` (shell variables are initialized from environment variables, after all, and remote exploitability of shellshock showed how environment variables can sometimes be remotely injected); with `sh "$SCRIPTS/$SCRIPTNAME" "$name"` that would just cause an error, whereas with `sh $SCRIPTS/$SCRIPTNAME $name` absent the quotes, it's arbitrary code execution). – Charles Duffy May 16 '17 at 04:05