Assigning a variable after the contents are 'cut' in bash - linux

I am iterating through a folder of files using bash, but I need to cut the preceding path. For instance if I have this '/temp/test/filename' I want to cut off the '/temp/test/' and store the file name to a variable so I can write a log with the filename in it.
Can anyone help me out? The problem is that the variable temp is always empty.
Here is my bash code:
#!/bin/bash
for file in /temp/test/*
do
if [[ ! -f "$file" ]]
then
continue
fi
temp="$file"|cut -d'/' -f3
$file > /var/log/$temp$(date +%Y%m%d%H%M%S).log
done
exit

Try that :
$ x=/temp/test/filename
$ echo ${x##*/}
filename
Another solution is to use basename :
$ basename /temp/test/filename
filename
The first solution is a parameter expansion and it's a bash builtin, so we increase performance.
Your line temp="$file"|cut -d'/' -f3 is broken.
when you want to store the output of a command in a variable, you should do var=$(command)
you need to pass the value to the STDIN of the command with a here-string (<<<) or with echo value | command
finally, if you'd want to use cut :
$ temp=$(cut -d/ -f4 <<< /temp/test/filename)
$ echo $temp
filename

Related

parsing complex string using shell script

I'm trying the whole day to find a good way for parsing some strings with a shell script. the strings are used as calling parameter for some applications.
they looks like:
parsingParams -c "id=uid5 prog=/opt/bin/example arg=\"-D -t5 >/dev/null 1>&2\" info='fdhff fd'" start
I'm only allowed to use shell-script. I tried to use some sed and cut commands but nothing works fine.
My tries are like:
prog=$(echo $# | cut -d= -f3 | sed 's|\s.*$||')
that return the correct value of prog but for the value of arg I couldn't find a good way to get it.
the info parameter is optional also it may be left.
may any one have a good idea that can solve this problem?
many thanks in advance
Looks like you could use eval to let the shell parse your input string, but if you don't control the input (if it comes from an unreliable source), that will introduce a major vulnerability (imagine an attacker somehow passes -c "rm -rf /" to your program).
A safer way would be to explicitly specify allowed forms of user input.
The problem you have with splitting on space (with cut) if the space is quoted, can be avoided if you specify valid fields (content, not separator), for example in GNU awk, you can use FPAT:
$ params="id=uid5 prog=/opt/bin/example arg=\"-D -t5 >/dev/null 1>&2\" info='fdhff fd'"
$ awk -v FPAT="[^=]+=(\"[^\"]*\"|'[^']*'|[^ ]*) *" '{for (i=1; i<=NF; i++) print $i}' <<<"$params"
id=uid5
prog=/opt/bin/example
arg="-D -t5 >/dev/null 1>&2"
info='fdhff fd'
Valid fields will be in one of the following forms:
var="val with spaces"
var='val with spaces'
var=val_no_spaces
Now with assignments split (one per line, assuming newline is not allowed in params), you can process them further, even with cut:
$ awk ... | cut -d $'\n' -f3
arg="-D -t5 >/dev/null 1>&2"
eval
$ eval "id=uid5 prog=/opt/bin/example arg=\"-D -t5 >/dev/null 1>&2\" info='fdhff fd'"
$ echo $id
uid5
$ echo $prog
/opt/bin/example
$ echo $arg
-D -t5 >/dev/null 1>&2
$ echo $info
fdhff fd

Linux: get specific field from filename

I am currently learning linux bash scripting:
I have files in a folder with the following filename-pattern:
ABC01_-12ab_STRINGONE_logicMatches.txt
DEF02_-12ab_STRINGTWO_logicMatches.txt
JKL03_-12ab_STRINGTHREE_logicMatches.txt
I want to extract STRINGONE, STRINGTWO and STRINGTHREE as a list. To see, if my idea works, I wanted to echo my result to bash first.
Code of my bash-script (executed in the folder, where the files are located):
#!/bin/bash
for element in 'folder' do out='cut -d "_" -f2 $element | echo $out' done
Actual result:
error: unexpected end of file
Desired result:
STRINGONE
STRINGTWO
STRINGTHREE
(echoed in bash)
The idea you are doing is right. But the syntax of file globbing (looking for text files) and command substitution (running the cut command) is wrong. You need to do
for file in folder/*.txt;
# This condition handles the loop exit if no .txt files are found, and
# not throw errors
[ -f "$file" ] || continue
# The command-substitution syntax $(..) runs the command and returns the
# result out to the variable 'out'
out=$(cut -d "_" -f3 <<< "$file")
echo "$out"
done

Linux : check if something is a file [ -f not working ]

I am currently trying to list the size of all files in a directory which is passed as the first argument to the script, but the -f option in Linux is not working, or am I missing something.
Here is the code :
for tmp in "$1/*"
do
echo $tmp
if [ -f "$tmp" ]
then num=`ls -l $tmp | cut -d " " -f5`
echo $num
fi
done
How would I fix this problem?
I think the error is with your glob syntax which doesn't work in either single- or double-quotes,
for tmp in "$1"/*; do
..
Do the above to expand the glob outside the quotes.
There are couple more improvements possible in your script,
Double-quote your variables to prevent from word-splitting, e.g. echo "$temp"
Backtick command substitution `` is legacy syntax with several issues, use the $(..) syntax.
The [-f "filename"] condition check in linux is for checking the existence of a file and it is a regular file. For reference, use this text as reference,
-b FILE
FILE exists and is block special
-c FILE
FILE exists and is character special
-d FILE
FILE exists and is a directory
-e FILE
FILE exists
-f FILE
FILE exists and is a regular file
-g FILE
FILE exists and is set-group-ID
-G FILE
FILE exists and is owned by the effective group ID
I suggest you try with [-e "filename"] and see if it works.
Cheers!
At least on the command line, this piece of script does it:
for tmp in *; do echo $tmp; if [ -f $tmp ]; then num=$(ls -l $tmp | sed -e 's/ */ /g' | cut -d ' ' -f5); echo $num; fi; done;
If cut uses space as delimiter, it cuts at every space sign. Sometimes you have more than one space between columns and the count can easily go wrong. I'm guessing that in your case you just happened to echo a space, which looks like nothing. With the sed command I remove extra spaces.

How to use a Linux variable as a command parameter

I am trying to use a bash shell variable as a command parameter but can't
Here is what works:
sed -n '2p' <file>
gives me line 2 of file
What I want to do:
sed -n '$variable p' <file>
Of course, this does not work. I have tried every possible syntax combination without success. How can I incorporate a variable in place of a constant?
Variables are expanded inside doublequotes, not inside singlequotes:
sed -n "$variable p" <file>
#Barmar has the right answer to your question.
I fear you are going to use this as a technique to iterate over the lines of a file.
This will be very inefficient:
for linenum in $(seq $(wc -l < filename)); do
line=$(sed -n "$linenum p" filename)
# do something with $line
done
The idiomatic way to iterate over the lines of a file is:
while IFS= read -r line; do
# do something with "$line"
done < filename
Put the variable outside the string:
sed -n $variable'p'

How to get Substring from Filename in Unix shellscripting

I want a shell script to get MMDDYYYY from the file with a name as mentioned below file
linuxbox.23566.MMDDYYYYHHMMSS.zip
Using bash string functions:
for file in *.zip; do
file="${file%.*}"
file="${file##*.}"
echo "${file:0:8}"
done
Explaination:
file="${file%.*}": Gets rid of the extension and stores the new name in file variable
file="${file##*.}": Gets rid of the longest match from beginning and stores the name in file variable
echo "${file:0:8}": echoes the first 8 characters of whats left.
Demo:
$ ls
linuxbox.23566.MMDDYYYYHHMMSS.zip
$ for file in *; do file="${file%.*}"; file="${file##*.}"; echo "${file:0:8}"; done
MMDDYYYY
With cut:
$ cut -d. -f3 <<< "linuxbox.23566.MMDDYYYYHHMMSS.zip" | cut -c-8
MMDDYYYY
Because the first part is returning:
$ cut -d. -f3 <<< "linuxbox.23566.MMDDYYYYHHMMSS.zip"
MMDDYYYYHHMMSS
And then it gets the first 8 chars.

Resources