How to move/copy a file to a sub-directory using awk in shell scripting - awk

Take a look at this Picture.
Here I have tried to check whether the value of P is <90 and if so then I want to move this file to good sub-directory(good is a sub-directory of RF2.0 directory)...
But unfortunately it copies the entire RF2.0 folder into the good sub-folder, after running this below code, which I don't want.
Here is my code:
for i in *.SAC
do
P=`saclhdr -USER5 $i`
`echo $P $i|awk '{if ($1<90) print $2}'|cp -R /home/sushrat/Downloads/RFevents/RUMJ/RF2.0/$2 /home/sushrat/Downloads/RFevents/RUMJ/RF2.0/good`
done
Any help to solve the issue is appreciated.

You can't just treat $2 in your awk as $2 in cp command. assign output of awk to a variable x then do whatever you want with $x as a filename "I guess".
for i in *.SAC
do
P=`saclhdr -USER5 $i`
x=`echo $P $i|awk '{if ($1<90) print $2}'`
cp -R /home/sushrat/Downloads/RFevents/RUMJ/RF2.0/$x /home/sushrat/Downloads/RFevents/RUMJ/RF2.0/good`
done

Related

qsub doesn't recognize awk field variables

Consider this awk script to print column #2 of every line:
awk '{print $2}' a.txt. $2 is not a shell variable, yet when I attempt to submit this code to qsub, $2 is interpreted as such. I.e.
qsub awk '{print $2}' a.txt
results in qsub executing the command
awk '{print }' a.txt
To be clear, I'm not trying to use a shell variable in an awk script; therefore How do I use shell variables in an awk script? is not applicable.
I tried suggestions in Using awk with qsub and issues with quotations, including \$2 and
qsub -- awk '{print $2}' a.txt.
Neither works.
I can certainly put awk in a script and call qsub that way, i.e., qsub awkscript.sh. However, if there's a way to use qsub+awk from the command line, I'd like to learn how.
does a double-layer quoting work, like
qsub 'awk '\''{ print $2 }'\'' a.txt '
RARE Kpop Manifesto below was 99% correct. With a backslash, the whole expression worked like magic :)
qsub 'awk '\''{ print \$2 }'\'' a.txt '

File size grows greatly after using awk

I want to add row number for a file, then I do like this,
awk '{print $0 "\x03" NR > "/opt/data2/gds_test/test_partly.txt"}' /opt/data2/gds_test/test_partly.txt
I put this line of command in a shell script file, and run it for some time, it still does not finish, so I end it by force, but I find the source file size has changed from 1.7G to 242G,
What happened? I am a little confused,
I had ever use a small file to test in command line, this awk command seems ok,
You're reading from the front of a file at the same time as you're writing onto the end of it. Try this instead:
tmp=$(mktemp)
awk '{print $0 "\x03" NR}' '/opt/data2/gds_test/test_partly.txt' > "$tmp" &&
mv "$tmp" '/opt/data2/gds_test/test_partly.txt'
yes, i change to redirect the result to a tmp file, and then delete the original file and rename the tmp file, it is ok,
and i just also get to know that gawk -I inplace can be used,

How do I append awk script to a file?

hello i have the following awk script:
#!/bin/awk -f
{for(i=4;i<=7;i++) j+=$i; print "Student",NR",",$1,$2",",j/4; j=0}
and i want to append the output to a new file (newfile.txt).
Could you please try following. Where mention output file inside awk code itself.
{for(i=4;i<=7;i++) j+=$i; print "Student" OFS NR",",$1,$2"," OFS j/4 >> (output_file); j=0}
OR 2nd way is when you are running your awk code where script is the script name you are calling to run your awk program eg-->
./script >> output_file
In case you want to run an awk one-liner to get output into a output file then try following.
awk -v output_file="Output.txt" '{for(i=4;i<=7;i++) j+=$i; print "Student" OFS NR",",$1,$2"," OFS j/4 >> (output_file); j=0}' Input_file
In above code I have created a variable named output_file whose value you could keep it as per your wish too.
Don't use a shebang to call awk from a shell script as it robs you of the ability to separate your functionality by what each (the shell or awk) does best. Make your shell script look like this instead (using whichever shell you use for the shebang):
#!/bin/env bash
awk '
{for(i=4;i<=7;i++) j+=$i; print "Student",NR",",$1,$2",",j/4; j=0}
' "$#" >> newfile.txt

Change a string using sed or awk

I have some files which have wrong time and date, but the filename contains the correct time and date and I try to write a script to fix this with the touch command.
Example of filename:
071212_090537.jpg
I would like this to be converted to the following format:
1712120905.37
Note, the year is listed as 07 in the filename, even if it is 17 so I would like the first 0 to be changed to 1.
How can I do this using awk or sed?
I'm quite new to awk and sed, an programming in general. Have tried to search for a solution and instruction, but haven't manage to figure out how to solve this.
Can anyone help me?
Thanks. :)
Take your example:
awk -F'[_.]' '{$0=$1$2;sub(/^./,"1");sub(/..$/,".&")}1'<<<"071212_090537.jpg"
will output:
1712120905.37
If you want the file to be removed, you can let awk generate the mv origin new command, and pipe the output to |sh, like: (comments inline)
listYourFiles| # list your files as input to awk
awk -F'[_.]' '{o=$0;$0=$1$2;sub(/^./,"1");sub(/..$/,".&");
printf "mv %s %s\n",o,$0 }1' #this will print "mv ori new"
|sh # this will execute the mv command
It's completely unnecessary to call awk or sed for this, you can do it in your shell. e.g. with bash:
$ f='071212_090537.jpg'
$ [[ $f =~ ^.(.*)_(.*)(..)\.[^.]+$ ]]
$ echo "1${BASH_REMATCH[1]}${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
1712120905.37
This is probably what you're trying to do:
for old in *.jpg; do
[[ $old =~ ^.(.*)_(.*)(..)\.[^.]+$ ]] || { printf 'Warning, unexpected old file name format "%s"\n' "$old" >&2; continue; }
new="1${BASH_REMATCH[1]}${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
[[ -f "$new" ]] && { printf 'Warning, new file name "%s" generated from "%s" already exists, skipping.\n' "$new" "$old" >&2; continue; }
mv -- "$old" "$new"
done
You need that test for new already existing since an old of 071212_090537.jpg or 171212_090537.jpg (or various other values) would create the same new of 1712120905.37
I think sed really is the easiest solution:
You could do this:
▶ for f in *.jpg ; do
new_f=$(sed -E 's/([0-9]{6})_([0-9]{4})([0-9]{2})\.jpg/\1\2.\3.jpg/' <<< $f)
mv $f $new_f
done
For more info:
You probably need to read an introductory tutorial on regular expressions.
Note that the -E option to sed allows use of extended regular expressions, allowing a more readable and convenient expression here.
Use of <<< is a Bashism known as a "here-string". If you are using a shell that doesn't support that, A <<< $b can be rewritten as echo $b | A.
Testing:
▶ touch 071212_090538.jpg 071212_090539.jpg
▶ ls -1 *.jpg
071212_090538.jpg
071212_090539.jpg
▶ for f in *.jpg ; do
new_f=$(sed -E 's/([0-9]{6})_([0-9]{4})([0-9]{2})\.jpg/\1\2.\3.jpg/' <<< $f)
mv $f $new_f
done
▶ ls -1
0712120905.38.jpg
0712120905.39.jpg

awk won't print new line characters

I am using the below code to change an existing awk script so that I can add more and more cases with a simple command.
echo `awk '{if(/#append1/){print "pref'"$1"'=0\n" $0 "\n"} else{print $0 "\n"}}' tf.a
note that the first print is "pref'"$1"'=0\n" so it is referring to the variable $1 in its environment, not in awk itself.
The command ./tfb.a "c" should change the code from:
BEGIN{
#append1
}
...
to:
BEGIN{
prefc=0
#append1
}
...
However, it gives me everything on one line.
Does anyone know why this is?
If you take awk right out of the equation you can see what's going on:
# Use a small test file instead of an awk script
$ cat xxx
hello
there
$ echo `cat xxx`
hello there
$ echo "`cat xxx`"
hello
there
$ echo "$(cat xxx)"
hello
there
$
The backtick operator expands the output into shell "words" too soon. You could play around with the $IFS variable in the shell (yikes), or you could just use double-quotes.
If you're running a modern sh (e.g. ksh or bash, not the "classic" Bourne sh), you may also want to use the $() syntax (it's easier to find the matching start/end delimiter).
do it like this. pass the variable from shell to awk properly using -v
#!/bin/bash
toinsert="$1"
awk -v toinsert=$toinsert '
/#append1/{
$0="pref"toinsert"=0\n"$0
}
{print}
' file > temp
mv temp file
output
$ cat file
BEGIN{
#append1
}
$ ./shell.sh c
BEGIN{
prefc=0
#append1
}