trying to write a bash where the command to be used is specified in a environmental variable, if it is defined. Doing so as follows:
if [ -z $MY_DIFF ];
then
echo Using standard diff $(which diff), change MY_DIFF env variable to use a different one.
echo $(which diff)
$diffv=$(which diff)
else
$diffv=$MY_DIFF
fi
$diffv c.xml c2.xml
But I'm getting:
./bash.sh: line 10: =/opt/gnu/bin/diff: No such file or directory
./bash.sh: line 13: c.xml: command not found
I'm sure the file exists and I do have permission to execute. Any idea what the problem might be?
Remove the extra $ before diffv assignment. Use:
diffv=$(which diff)
And:
diffv=$MY_DIFF
With $ you get:
<diffv value, empty>=<MY_DIFF value, or which diff>
=/opt/gnu/bin/diff
Related
Ive got a .sql job which creates files depending on certain criteria, it writes these with a prefix of TEMP_ as we then have an adaptor that picks up the files and we dont want them picked up before writing is complete.
I need to put a post job in place which renames these files, i have it set up with a number of other job but they all create the files each time they run. This job only creates the files sometimes it runs, depending on the data in the system.
I need to do a check if the file exists and then exit if no file exists.
Ive found a few examples but they all seem to fail, this is where i have got to which i thought was checking if no file, if no file then exit but it fails and displays:
"syntax error at line 16: `TEMP_SUBCON*.csv' unexpected"
This is what i have currently with line 16 being the first line - Above that is just comments:
if [[ ! -f $OUT_DIR -name TEMP_SUBCON*.csv ]] ; then
exit $?
fi
TEMP_DATA_FILE=$(find $OUT_DIR -name TEMP_SUBCON_QTY_output*.csv)
DATA_FILE=$(basename $TEMP_DATA_FILE | cut -c6-)
echo $TEMP_DATA_FILE
echo $DATA_FILE
## Rename the file name, remove the phrase TEMP_, so that EAI can pick the file ##
mv $TEMP_DATA_FILE $OUT_DIR/$DATA_FILE
Can you help guide what ive done incorrectly?
Thanks
If I understand it right, you want to find the files with TEMP_ prefix in your $OUT_DIR, and then if any rename them without the prefix. Then that should do the trick
for file in $OUT_DIR/TEMP_SUBCON_*.txt; do
if [[ -e $file ]]; then
mv $file $OUT_DIR/${file#*SUBCON_}
fi
done
exit
It will go through the directory finding each TEMP_ file and rename them without it. If there is none, it won't do anything.
That syntax is not valid for the [[ ... ]] test.
Why not use the result of the subsequent find command to check if there were any matching files in the specified directory instead, and quit if no files are returned (in other words, quit if the result variable is empty)?
Example:
TEMP_DATA_FILE=$(find $OUT_DIR -name "TEMP_SUBCON_QTY_output*.csv" )
if [[ -z ${TEMP_DATA_FILE:=""} ]] ; then
exit 1
fi
Note 1: you should quote the pattern argument for the find command as shown.
Note 2: it is useful to use set -u in your ksh scripts to cause ksh to abort if variables are unitialized when used (often the cause of errors) , instead of using a default value. However, if you use use set -u then in any test you should explicitly give your own default value. That is the reason for using ${TEMP_DATA_FILE:=""} instead of ${TEMP_DATA_FILE} - to support the often very useful set -u option. Even when you do not use set -u the ${TEMP_DATA_FILE:=""} inside tests makes it explicit what should happen instead of relying on implicit behaviour.
Note 3: you should use set -x when debugging and study every line of the output, it will show you exactly what commands ran with which arguments and what was the result. This helps you to learn how to code in ksh and similar shells.
Trying to write a bash script to copy a large number of files from an external drive into separate directories based on a subject id.
I've included the script I've written below.
I get the following error:
cat: /Volumes/Seagate: No such file or directory
cat: Backup: No such file or directory
cat: Plus: No such file or directory
cat: Drive/Subject_List.txt: No such file or directory
When I try to copy a single file at a time using the terminal, it copies using the exact command I've put in this script. I'm not sure why it's not recognizing the directory when I try and use it in the script below. Any help is greatly appreciated!
#!/bin/bash
#A bash script to copy the structural and functional files into the HCP_Entropy folder
#subject list
SUBJECT_LIST="/Volumes/Seagate/Backup/Plus/Drive/Subject_List.txt
for j in $(cat ${SUBJECT_LIST}); do
echo ${j}
cp /Volumes/Seagate\ Backup\ Plus\ Drive/HCP_DATA/Structural/{j}/unprocessed/3T/T1w_MPR1/${j}_3T_T1w_MPR1.nii.gz /Users/myname/Box/HCP_Entropy/BEN/${j}/anat
done
the line
$SUBJECT_LIST=/Volumes/Seagate\ Backup\ Plus\ Drive/Subject_List.txt
is bogus.
to assign values to a variable, you must not add the $ specifier.
a token starting with $ will be expanded, so $SUBJECT_LIST=... will first be expanded to =... (since you haven't assigned anything to the SUBJECT_LIST variable yet it is empty).
the proper way would be:
SUBJECT_LIST="/Volumes/Seagate Backup Plus Drive/Subject_List.txt"
(this uses quotes instead of escaping each space, which i find much more readable)
you also need to quote variables in case they contain spaces, else they might be interpreted by the command (cp) as multiple arguments.
for j in $(cat "${SUBJECT_LIST}"); do
# ...
done
and of course, you should check whether the source file actually exists, just like the destination directory.
indir="/Volumes/Seagate Backup Plus Drive"
SUBJECT_LIST="${indir}/Subject_List.txt"
cat "${SUBJECT_LIST}" | while read j; do
infile="${indir}/HCP_DATA/Structural/${j}/unprocessed/3T/T1w_MPR1/${j}_3T_T1w_MPR1.nii.gz"
outdir="/Users/myname/Box/HCP_Entropy/BEN/${j}/anat"
mkdir -p "${outdir}"
if [ -e "${infile}" ]; then
cp -v "${infile}" "${outdir}"
else
echo "missing file ${infile}" 1>&2
fi
done
Assume this file tree:
$PWD
____dir1
________file.one
________file.two
____dir2
________file.one
________file.two
I want to replace contents of file.one in each directory, with contents of corresponding file.two in that same directory.
I use the following code to accomplish this simple task:
cat ./*1/*.one > ./*1/*.two
cat ./*2/*.one > ./*2/*.two
It works as intended, BUT when I try to execute this like this:
/bin/sh -c 'cat ./*1/*.one > ./*1/*.two'
/bin/sh: ./*1/*.two: No such file or directory
The following error ^^ occurs.
NOTE: When I use Bash instead of Shell everything works even with -c flag.
The code in question is extremely fragile. If you generate your output name from your input file name, and avoid assuming that it already exists (and that there's exactly one match), you're on much firmer ground:
set -- ./*1/*.one # replace "$#" with list of matches for ./*1/*.one
for arg do # this is shorthand for: for arg in "$#"; do
[ -e "$arg" ] || continue # ignore files that don't exist (f/e, failed matches)
cat "$arg" >"${arg%.one}.two" # use a PE to replace .one with .two in output name
done
...which is to say, the following works as-intended on all POSIX-compliant shells:
sh -c 'set -- ./*1/*.one; for arg do [ -e "$arg" ] || continue; cat "$arg" >"${arg%.one}.two"; done'
See the bash-hackers' wiki page on parameter expansion for details on the ${arg%.one} syntax.
Always i get "Source file not readable or exists, please check the file " for the below code. I use cygwin in my windows machine to run the script. I am getting the same message even when the file is present in the location. How can i get more details as why the file is not readable.
#!/bin/ksh
#
# Scanning source file for existance and readable
file_loc="abc.xml"
if [ -f "$file_loc" -a -r "$file_loc"]
then
print "Source file read.\n"
else
print "Source file not readable or exists, please check the file $file_loc.\n"
fi
A space before the closing bracket is needed:
if [ -f "$file_loc" -a -r "$file_loc" ]
file_loc="abc.xml" && (< ${file_loc:?})
is an alternative check. An advantage is that it returns different messages for different errors; we let the shell do all the work.
How is this constructed? This single line can trigger at least three different messages:
The ${ varname :? optional message } syntax will check for undefined variables,
which can signal a typo in the variable name.
(< ${file_lo:?} )
-bash: file_lo: parameter null or not set
(< filename ) will just attempt to open and close the file.
$ (< nonesuch ) && echo ok
-bash: nonesuch: No such file or directory
$ (< /etc/shadow ) && echo ok
-bash: /etc/shadow: Permission denied
I am attempting to write a script that will generate a random number and then make a directory called that random number and copy in a text file. I have tried everything i could think of the assign the variable but each time i get
RANDOM: command not found
RANDOM: command not found
bash: //small.txt: No such file or directory
bash: //small.txt: No such file or directory
Below is my code
#!/bin/bash
one=$(RANDOM)
two=$(RANDOM)
mkdir -p $one
mkdir -p $two
echo “BIGGGGGONgrery54y457457yytewrterytyutytytyhtytryrtyrthrthtrhrtyhrthrhtrhrthrthrthrthE”| > $one/small.txt
echo “B”| > $two/small.txt
echo "finish -l test me "
done
It's not illegal syntax (it does mean something), it's just the wrong syntax for what you want. Instead of $(RANDOM) you want ${RANDOM} or even just $RANDOM.
When you use $() it's a command substitution, so bash is literally trying to execute a command named RANDOM, which is why you get command not found and nothing in your variables.
Your I/O redirection also looks wrong... to write to a file you should use:
echo "something" > file
Note that I removed the |.
FatalError covered the syntax problem, here's something related - how to generate a random number within a range (in this example, 1-100):
NUMBER=$(( ( $RANDOM % 100 ) + 1 ))
Also see: http://www.cyberciti.biz/faq/bash-shell-script-generating-random-numbers/ for other methods / information about random number generation in shell