How to get extension of a file in shell script - linux

I am trying to get file extension for a file in shell script. But without any luck.
The command I am using is
file_ext=${filename##*.}
and
file_ext = $filename |awk -F . '{if (NF>1) {print $NF}}'
But both of the commands failed to put value in variable file_ext. But when i try
echo $filename |awk -F . '{if (NF>1) {print $NF}}'
It gives me the desired result. I am new to shell script. Please describe the situation what is happening. And also how should I do it?
Thanks.

to get file extension, just use the shell
$ filename="myfile.ext"
$ echo ${filename##*.}
ext
$ file_ext=${filename##*.} #put to variable
$ echo ${file_ext}
ext

Spaces hurt.
Anyway you should do:
file_ext=$(echo $filename | awk -F . '{if (NF>1) {print $NF}}')
[Edit] Better suggestion by Martin:
file_ext=$(printf '%s' "$filename" | awk -F . '{if (NF>1) {print $NF}}')
That will store in $file_ext the output of the command.

You have to be careful when declaring variables.
variable1="string" # assign a string value
variable3=`command` # assign output from command
variable2=$(command) # assign output from command
Notice that you cannot put a space after the variable, because then it gets interpreted as a normal command.

Related

awk command not outputting(awk: error cant open source file)

Hey guys I'm trying to delete everything after the last / in a string (the parameter). I'm getting some issues that I can't quite figure out.. Sorry in advance for any stupid mistake I've made
myvar1 = $(echo $1 | awk -f "/" '(print $NF)')
Sample input:
./root/desktop/test
Sample output:
test
You should be using -F, not -f but there's other issues too. Change the whole line to:
myvar1=$(echo "$1" | awk -F'/' '{print $NF}')
IF you really want to use echo, awk and a pipe for this instead of just a bash builtin.
Also, the above selects whats after the last '/' not deletes everything after it so its not clear what you really want. Post some sample input and expected output if you can't figure it out from this:
$ x="a/b/c/d"; echo "${x##*/}"
d
$ x="a/b/c/d"; echo "${x%/*}"
a/b/c
Just another solution:
$ x=`basename /a/b/file`; echo $x
file
$ x=`dirname /a/b/file` ; echo $x
/a/b

Bash script to remove last three charater in a file name

For ex the file is this:
NBDG6_CDRCCN_4004_-TTNBDG6_CCN_51-140108-1433-802580.00.Blk32768Blk.CCN:00
I want to rename this file to:
NBDG6_CDRCCN_4004_-TTNBDG6_CCN_51-140108-1433-802580.00.Blk32768Blk.CCN
Using ${parameter%word} (Remove matching suffix pattern):
$ echo "$fn"
NBDG6_CDRCCN_4004_-TTNBDG6_CCN_51-140108-1433-802580.00.Blk32768Blk.CCN:00
$ echo "${fn%:*}"
NBDG6_CDRCCN_4004_-TTNBDG6_CCN_51-140108-1433-802580.00.Blk32768Blk.CCN
Using cut
$ echo $fn
NBDG6_CDRCCN_4004_-TTNBDG6_CCN_51-140108-1433-802580.00.Blk32768Blk.CCN:00
$ echo $fn |cut -d: -f1
NBDG6_CDRCCN_4004_-TTNBDG6_CCN_51-140108-1433-802580.00.Blk32768Blk.CCN
Using awk
echo $fn |awk -F : '{print $1}'
more ways...
According to the link here:
This should work:
awk '{old=$0;gsub(/...$/,"",$0);system("mv \""old"\" "$0)}'
provided the file name is given as input.
For eg:
ls -1 NBDG6_CDRCCN_4004_-TTNBDG6_CCN_51-140108-1433-802580.00.Blk32768Blk.CCN:00|nawk '{old=$0;gsub(/...$/,"",$0);system("mv \""old"\" "$0)}'
Rename file using bash string manipulations:
# Filename needs to be in a variable
file=NBDG6_CDRCCN_4004_-TTNBDG6_CCN_51-140108-1433-802580.00.Blk32768Blk.CCN:00
# Rename file
mv "$file" "${file%???}"
This removes the last three characters from filename.
Using just bash:
fn='NBDG6_CDRCCN_4004_-TTNBDG6_CCN_51-140108-1433-802580.00.Blk32768Blk.CCN:00'
mv "$fn" "${fn::-3}"
if you have Ruby
echo NBDG6_CD* | ruby -e 'f=gets.chomp;File.rename(f, f[0..-4])'

Pass parameter to an awk script file

If I want to pass a parameter to an awk script file, how can I do that ?
#!/usr/bin/awk -f
{print $1}
Here I want to print the first argument passed to the script from the shell, like:
bash-prompt> echo "test" | ./myawkscript.awk hello
bash-prompt> hello
In awk $1 references the first field in a record not the first argument like it does in bash. You need to use ARGV for this, check out here for the offical word.
Script:
#!/bin/awk -f
BEGIN{
print "AWK Script"
print ARGV[1]
}
Demo:
$ ./script.awk "Passed in using ARGV"
AWK Script
Passed in using ARGV
You can use -v as a command-line option to provide a variable to the script:
Say we have a file script.awk like this:
BEGIN {print "I got the var:", my_var}
Then we run it like this:
$ awk -v my_var="hello this is me" -f script.awk
I got the var: hello this is me
your hash bang defines the script is not shell script, it is an awk script. you cannot do it in bash way within your script.
also, what you did : echo blah|awk ... is not passing paramenter, it pipes the output of echo command to another command.
you could try these way below:
echo "hello"|./foo.awk file -
or
var="hello"
awk -v a="$var" -f foo.awk file
with this, you have var a in your foo.awk, you could use it.
if you want to do something like shell script accept $1 $2 vars, you can write a small shellscript to wrap your awk stuff.
EDIT
No I didn't misunderstand you.
let's take the example:
let's say, your x.awk has:
{print $1}
if you do :
echo "foo" | x.awk file
it is same as:
echo "foo"| awk '{print $1}' file
here the input for awk is only file, your echo foo doesn't make sense. if you do:
echo "foo"|awk '{print $1}' file -
or
echo "foo"|awk '{print $1}' - file
awk takes two input (arguments for awk) one is stdin one is the file, in your awk script you could:
echo "foo"|awk 'NR==FNR{print $1;next}{print $1}' - file
this will print first foo from your echo, then the column1 from file of course this example does nothing actual work, just print them all.
you can of course have more than two inputs, and don't check the NR and FNR, you could use the
ARGC The number of elements in the ARGV array.
ARGV An array of command line arguments, excluding options and the program argument, numbered from zero to ARGC-1
for example :
echo "foo"|./x.awk file1 - file2
then your "foo" is the 2nd arg, you can get it in your x.awk by ARGV[2]
echo "foo" |x.awk file1 file2 file2 -
now it is ARGV[4] case.
I mean, your echo "foo"|.. would be stdin for awk, it could by 1st or nth "argument"/input for awk. depends on where you put the -(stdin). You have to handle it in your awk script.

linux shell storing path

I want to find the path of folder and store it into a variable
#!/bin/bash
howdy=$(whereis yum.repos.d)
howdy=$howdy"/remi.repo"
echo $howdy
The issue is that when I want to use the variable $howdy , it will output
yum.repos: /etc/yum.repos.d/remi.repo
I want it to be just the path
/etc/yum.repos.d/remi.repo
so I could use it in my code
You can use Parameter Expansion:
${howdy#yum.repos: }
You can erase the first part of the string:
echo ${howdy##*: }
Or you can pipe it through cut -d' ' -f2
you can use awk to format the output:
howdy=$(whereis yum.repos.d| awk '{print $2}')
Full code:
#!/bin/bash
howdy=$(whereis yum.repos.d| awk '{print $2}')
howdy=$howdy"/remi.repo"
echo $howdy
this will output: /etc/yum.repos.d/remi.repo
How about:
howdy=$(find /etc -type f -name remi.repo)
whereis yum.repos.d | awk -F: '{print $2}' will give strip off the first part

awk script header: #!/bin/bash or #!/bin/awk -f?

In an awk file, e.g example.awk, should the header be #!/bin/bash or #!/bin/awk -f?
The reason for my question is that if I try this command in the console I receive the correct file.txt with "line of text":
awk 'BEGIN {print "line of text"}' >> file.txt
but if i try execute the following file with ./example.awk:
#! /bin/awk -f
awk 'BEGIN {print "line of text"}' >> file.txt
it returns an error:
$ ./awk-usage.awk
awk: ./awk-usage.awk:3: awk 'BEGIN {print "line of text"}' >> file.txt
awk: ./awk-usage.awk:3: ^ invalid char ''' in expression
If I change the header to #!/bin/bash or #!/bin/sh it works.
What is my error? What is the reason of that?
Since you explicitly run the awk command, you should use #!/bin/bash. You can use #!/bin/awk if you remove the awk command and include only the awk program (e.g. BEGIN {print "line of text"}), but then you need to append to file using awk syntax (print ... >> file).
awk -f takes a file containing the awk script, so that is completely wrong here.
Your script is a shell script that happens to contains an awk command.
#! /bin/sh tells your shell to execute the file as a shell command with /bin/sh - and it is a shell command. If you replace that with #! /bin/awk -f then the file is executed with awk, basically the same as executing
/bin/awk -f awk 'BEGIN {print "line of text"}' >> file.txt

Resources