I have a requirement which needs to pass a parameter when calling the script, using this parameter to find a file name stored in master file. then read the file content. the issue is in the file name has a special character "$". don't know how to handle this. below is example:
the master file is:
abc, v$xyz
bcd, x$efg
my script like:
#!/bin/ksh
genfile=$1
while IFS=',' filedir, name
do
cd $filedir
if [ -f ${genfile}* ]; then
cat $name ... "read the file and do something.
fi
done < Masterfile
the real file name like v$xyz_xxxx_xxxx.xxx
I call the script: ksh scriptname 'v$xyz'.
without "$", the script. with "$", I can put single quote when call the script, but in the script, I don't know how to add single quote in variable "name". please share you idea with me how to handle this.
I know I need to wrap the code with code tag, for some reason, the code tag doesn't work for me.
thanks Corona688.
the variable is "v$xyz", the file name like v$xyz_xxxx_xxxx.txt.
basically, I want to use variable "v$xyz" to find "v$xyz_xxxx_xxxx.txt" in the directory, if the file exist, then copy file to ABCD_v$xyz.txt. the directory name saved in master file with .
'name' is the variable, 'v$xyz' is the value it holds.
The $ is not a problem at all then, the shell won't do anything weird with it. Your [ -f ... ] is problematic though, since * returns more than one file sometimes, which would be a syntax error. So, how about this?
#!/bin/ksh
genfile="$1"
while IFS=", " read filedir name
do
echo "filedir [$filedir] name [$name]"
set -- "${name}"* # Overwrites $1, $2, etc with file1, file2, ...
if [ -f "$1" ]
then
echo "Found file $1"
fi
done < masterfile
No, it is not. A "variable" is something like "$name" or "${name}", where "name" is a name you choose. "$xyz" might be a variable, but "v$xyz" is a literal "v" followed by the content of a variable with the name "xyz".
OK, but is the "$xyz" in this filename now meant literally or should that signify the variable portion of the filename which you want to transport via the variable? If the first is the case a simple quotation will suffice, because this is what it is for - inside of (single) quotes the "$" loses its special meaning to the shell and reverts back to a normal character:
ls -l v$xyz_xxxx_xxxx.txt
will first replace "$xyz_xxxx_xxxx" with the content of a variable named "xyz_xxxx_xxxx" (which most probably will not exist so that it evaluates to "", the empty string) and therefore search for a file named "v.txt". Whereas:
ls -l 'v$xyz_xxxx_xxxx.txt'
(notice the single quotes) will look for a file named exactly this: "v$xyz_xxxx_xxxx.txt".
If "$xyz" is a variable and you want to use that as the changing part of an otherwise fixed filename then this code snippet is for you:
xyz="some$thing"
ls -l "v${xyz}_xxxx_xxxx.txt"
This will search for a file name "vsome$thing_xxxx_xxxx.txt". Because of the braces around "xyz" the shell knows that only this (and not the rest of the string) is the name of the variable. Notice the double quotes: you should habitually double-quote every use of any variable - ever and always! (There are only very few exceptions to this rule of thumb.) This way blanks (yes, filename can contain blanks) will not break your script.
Pseudocode which doesn't do what you want really doesn't tell us what you do want. What is $1 here? And what is 'grep $1' for? It's not going to do anything where you've put it.
Also, I noted above that [ -f * ] is a bad idea since it will fail with syntax errors whenever you match more than one file.
Also, you're still not quoting any of your variables and really should be.
thanks Corona688 for the explanation.
my bad, I didn't explain it clearly.
the requests is pass a value (eg: v$abc) when calling the script, get file directory and file name from master file. (below is sample master file), then go to corresponding directory, rename file (may need split the file as well). below pseudocode is testing code to check I can use variable with "$" sign. yes, there may have more than one files matching. could you please advise the best way to handle multiple matches. thanks in advance
I already showed you one way, if you don't like it, perhaps you need to tell me what you're expecting to happen.
And your code still has that grep on the end which will do exactly nothing where you've put it and I don't know what you're expecting it to do if you put it anywhere else. What is it for?
command to call the script:
ksh scriptname 'v$abc'
OK, questions remaining:
"variable with $" -- We already told you v$abc is not a variable, so what do you mean now?
Splitting the file -- when do you want this to happen, why, how?
Multiple matches -- what do you top expect to happen, why, how?
I think I finally get it -- that grep is supposed to find the line in the file you want. What for, I'm not certain, as you don't use the file for anything, yet. So I'm also wild-guessing that the 'dir' part of the file ends up being part of the destination file name.
Please try this code and see if it does anything like what you want. It won't actually move any files, just print 'mv inputfile outputfile'.
#!/bin/ksh
# We use a function, so overwriting $1 $2 ... won't affect anything outside
function checkfile {
dir="$1"
set -- "${2}"* # Match one or more files, placing in local $1 $2 ...
if [ ! -f "${1}" ]
then
echo "${1} not found" >&2
return 1
fi
echo mv "${1}" "${1}_${dir}"
}
while IFS=", " read dir filename # Split input upon spaces and commas
do
# Skip lines where filename doesn't match the argument given.
[ "$1" = "$filename" ] || continue
# call checkfile. Inside checkfile, $1=$dir and $2=$filename
checkfile "$dir" "$filename"
done<masterfile