cat: can't open '/tmp/drive/P0.RAW': No such file or directory - shell

The script pasted below causes the following error:
cat: can't open '/tmp/drive/P0.RAW': No such file or directory
It looks like the script does not properly evaluate $N for the filename.
How $N be made to evaluate so the file name is something like P01L.RAW, P02L.RAW, etc.?
N=1
until [ $N -ge 10 ]; do
cat bmpheader.bmp /tmp/drive/P0$NL.RAW > ./P0$NL.bmp
./quality_metric_test ./P0$NL.bmp
N=$((N + 1))
done

Your problem is that bash interprets all uppercase characters as part of the variable by default, so it's looking for $NL instead of just $N. This is why it returns just P0.RAW, as $NL is an unexisting variable. You can easily avoid that by a minor syntax adjustment, call the variable with curly brackets ({ and }) around it. Replace this:
cat bmpheader.bmp /tmp/drive/P0$NL.RAW > ./P0$NL.bmp
./quality_metric_test ./P0$NL.bmp
With this:
cat bmpheader.bmp /tmp/drive/P0${N}L.RAW > ./P0${N}L.bmp
./quality_metric_test ./P0${N}L.bmp
That should do the trick.

Related

redirect file names into a variable

Assume there are several files like the following
CLIENT_1.csv
CLIENT_2.csv
CLIENT_3.csv
CLIENT_4.csv
Is there any shell command/awk that we can use to direct the 1,2,3,4 into a variable named "ID"? So that we can do the following
if [ ${ID} != 4 ]
then
blah blah blah
fi
To get the number part for each file:
for file in CLIENT_*.csv ; do
id=${file%.csv} # remove trailing '.csv'
id=${id#CLIENT_} # remove leading 'CLIENT_'
if [ "$id" != 4 ] ; then ... ; fi
done
This is pretty much a repeat of this question.
How to iterate over files in a directory with Bash?
It uses filename wildcarding to iterate through the list. In your case you would use:
for filename in /mydirectory/CLIENT_*.csv; do
#whatever you wanted to do
done
Here is another way to do it where the filename string pattern is a variable.
bash: filenames with wildcards in variables
The file names are stored in the variable file (looking at the accepted answer) after the wildcarding is expanded in the for loop initialization. Again using the power of wildcarding your example would look something like this:
putfile=CLIENT_*.csv
for file in $putfile; do #whatever you wanted to do
done

Read variables from file and loop through them in bash

I have a text file containing variables like this:
lane1_pair1="file1"
lane1_pair2="file2"
lane2_pair1="file3"
lane2_pair2="file4"
...
I'd like to loop through the variables and concatenate all of them in a single file. I am applying the loop as:
. variables
for (( n=1; n<=no_lanes; n++ )) {
cat $"lane"${n}_pair1 >> "$sampleID"_cat1.fq
cat $"lane"${n}_pair2 >> "$sampleID"_cat2.fq
}
"$sampleID"_cat1.fq > fq_align_1
"$sampleID"_cat2.fq > fq_align_2
The problem here is that, cat command does not work because instead of replacing the "laneX_pairY" with its value, treat it as a string. I was wondering if anyone here has any idea about this.
As I see it, the problem is you're looping through variables that are named like an array but aren't one. Then you're in the position of trying to evaluate the contents of the variable name created from your other indexing variable, which is a recipe for messy code that breaks easily. I recommend making actual arrays of file names from your variables file:
p1_files=($(grep 'pair1' variables | cut -d '=' -f 2))
p2_files=($(grep 'pair2' variables | cut -d '=' -f 2))
for f in "${p1_files[#]}"; do
cat "${f//\"/}" >> "$sampleID"_cat1.fq
done
for f in "${p2_files[#]}"; do
cat "${f//\"/}" >> "$sampleID"_cat2.fq
done
I'm not sure how you want your fq_align_n variables to be, but you can read the file contents to variables using:
fq_align_1=$(cat "$sampleID"_cat1.fq)
fq_align_2=$(cat "$sampleID"_cat2.fq)
Or just skip the file creation altogether and build the variables incrementally in the loops.

Bash scripting: variable is not incrementing correctly

I am writing a bash script to loop through all the directories and rename the directory to the value of the array, but it seems my (i th) value is not incrementing correctly and it also says "(i th) command not found" when I run my bash script.
Here is my code: I replaced the values inside Unix with place holder values.
#!/bin/bash
declare -a Unix=(value1 value2 value3 .... );
i = 0
for d in */; do
echo ${Unix[$i]}
#mv $d ${Unix[$i]}
(($i+1))
done
You are doing two things wrong. Firstly , to answer your problem,
(($i+1))
should be
(($i+=1))
also, you should remove the spaces in the line
i = 0
so it looks like
i=0
Firstly, you might want to quote your directory names in the mv command, or you get into trouble with names containing spaces:
mv "$d" "${Unix[i]}"
As you see, it's not necessary to prepend the i in the index with $, as [] is an "arithmetic context" here and expands variable names.
Secondly, your increment does nothing: you just add 1 to i and throw the result away. You can use the increment operator instead:
(( ++i ))
Again, the $ is not needed.

read multiple values from a property file using bash shell script

Would like to read multiple values from a property file using a shell script
My properties files looks something like below, the reason I added it following way was to make sure, if in future more students joins I just need to add in in the properties file without changing any thing in the shell script.
student.properties
total_student=6
student_name_1="aaaa"
student_name_2="bbbb"
student_name_3="cccc"
student_name_4="dddd"
student_name_5="eeee"
When I run below script I not getting the desired output, for reading the student names from properties file
student.sh
#!/bin/bash
. /student.properties
i=1
while [ $i -lt $total_student ]
do
{
std_Name=$student_name_$i
echo $std_Name
#****** my logic *******
} || {
echo "ERROR..."
}
i=`expr $i + 1`
done
Output is something like this
1
2
3
4
5
I understand the script is not getting anything for $student_name_ hence only $i value is getting printed.
Hence, wanted to know how to read values from the properties file.
You can do variable name interpolation with ${!foo}. If $foo is "bar", then ${!foo} gives you the value of $bar. In your code that means changing
std_Name=$student_name_$i
to
var=student_name_$i
std_Name=${!var}
Alternatively, you could store the names in an array. Then you wouldn't have to do any parsing.
student.properties
student_names=("aaaa" "bbbb" "cccc" "dddd" "eeee")
student.sh
#!/bin/bash
. /student.properties
for student_name in "${student_names[#]}"; do
...
done
You can use indirect expansion:
std_Name=student_name_$i
echo "${!std_Name}"
the expression ${!var} basically evaluates the variable twice:
first evaluation: student_name_1
second evaluation: foo
Note that this is rarely a good idea and that using an array is almost always preferred.

Bash: iterate through files based on regex parameter

There are several posts about iterating through bash files like this:
count_files() {
count=0
for f in "filename_*.txt"
do
count=$(($count + 1))
done
echo "Current count:$count"
}
I need to pass in "filename_*.txt" as a param when calling the bash script. Like this:
$: count_files.sh "filename_*.txt"
$: count_files.sh "different_filename_*.txt"
This, however, only gets the first file:
count_files() {
count=0
for f in $1
do
count=$(($count + 1))
done
echo "Current count:$count"
}
How do I pass in a regex param and iterate through it?
NOTE: counting the files is just an example. If you have a simple way to do that, please share, but that's not the main question.
Inside count_files.sh script make sure you call function with quotes like this:
count_files "$1"
instead of:
count_files $1
Later will get you count=1 because wildcard will be expanded before function call to the first file name.

Resources