execute cut command inside bash script - linux

Every line printed with the echo includes the forward slashes for the directories that the given files are in. I am trying to cut the forward slashes using the cut command but it is not working. The files are gzipped so they have the .gz extension.
#!/bin/bash
for filename in /data/logs/2017/month_01/201701*
do
echo $filename
cut $filename -d '/' -f1
done
Thanks in advance.

The order of commands is wrong. You need to stream the string input to the cut command via pipe(|) or here-strings(<<<).
echo "$filename" | cut -d '/' -f1
(or)
cut -d '/' -f1 <<<"$filename"
(or) using here-docs
cut -d '/' -f1 <<EOF
$filename
EOF
data
And don't forget to double-quote variables to avoid Word-Splitting done by the shell.

Assuming filename is /a/b/c.gz you just want c.gz ?
Well there's two very easy answers:
basename $filename
The other is:
echo ${filename##*/}
The latter make use bash's built-in string delete parameter expansion.
Another way of solving your problem, is you could change directory first, i.e.
#!/bin/bash
pushd /data/logs/2017/month_01
for filename in 201701*
do
echo $filename
done
popd
Reference:
http://wiki.bash-hackers.org/syntax/pe
(EDIT: Fixed typo identified by #123)

As suggested b #lnian cut command used with echo command via pipe sign
For getting only file name with your script you need to use.
cut with -f1 option will get first value before / which would give blank so you need to get last value from the filename.
#!/bin/bash
for filename in /data/logs/2017/month_01/201701*
do
echo "$filename" | rev| cut -d '/' -f1
done
rev command reverse the filename so you will get last value which is your filename

Related

how to remove the extension of multiple files using cut in a shell script?

I'm studying about how to use 'cut'.
#!/bin/bash
for file in *.c; do
name = `$file | cut -d'.' -f1`
gcc $file -o $name
done
What's wrong with the following code?
There are a number of problems on this line:
name = `$file | cut -d'.' -f1`
First, to assign a shell variable, there should be no whitespace around the assignment operator:
name=`$file | cut -d'.' -f1`
Secondly, you want to pass $file to cut as a string, but what you're actually doing is trying to run $file as if it were an executable program (which it may very well be, but that's beside the point). Instead, use echo or shell redirection to pass it:
name=`echo $file | cut -d. -f1`
Or:
name=`cut -d. -f1 <<< $file`
I would actually recommend that you approach it slightly differently. Your solution will break if you get a file like foo.bar.c. Instead, you can use shell expansion to strip off the trailing extension:
name=${file%.c}
Or you can use the basename utility:
name=`basename $file .c`
You should use the command substitution (https://www.gnu.org/software/bash/manual/bashref.html#Command-Substitution) to execute a command in a script.
With this the code will look like this
#!/bin/bash
for file in *.c; do
name=$(echo "$file" | cut -f 1 -d '.')
gcc $file -o $name
done
With the echo will send the $file to the standard output.
Then the pipe will trigger after the command.
The cut command with the . delimiter will split the file name and will keep the first part.
This is assigned to the name variable.
Hope this answer helps

change name of file in nested folders

I have been trying to think of a way to rename file names that are listed in nested folders and am having an issue resolving this matter. as a test i have been able to cut out what part of the name i would like to alter but can't think of how to put that into a variable and chain the name together. the file format looks like this.
XXX_XXXX_YYYYYYYYYY_100426151653-all.mp3
i have been testing this format out to cut the part out i was looking to change but i am not sure this would be the best way of doing it.
echo XXX_XXXX_YYYYYYYYYY_100426095135-all.mp3 |awk -F_ '{print $4}' | cut -c 1-6
I would like to change the 100426151653 to this 20100426-151653 format in the name.
i have tried to use the rename the file with this command with this format 's/ //g' but that format did not work i had to resort to rename ' ' '' file name to remove a blank space.
so the file would start as this
XXX_XXXX_YYYYYYYYYY_100426151653-all.mp3
and end like this
XXX_XXXX_YYYYYYYYYY_20100426-151653-all.mp3
How about using find and a bash function
#!/bin/bash
modfn () {
suffix=$2
fn=$(basename $1)
path=$(dirname $1)
fld1=$(echo $fn | cut -d '_' -f1)
fld2=$(echo $fn | cut -d '_' -f2)
fld3=$(echo $fn | cut -d '_' -f3)
fld4=$(echo $fn | cut -d '_' -f4)
fld5=${fld4%$suffix}
l5=${#fld5}
fld6=${fld5:0:$(($l5 - 6))}
fld7=${fld5:$(($l5 - 6)):6}
newfn="${fld1}_${fld2}_${fld3}_20${fld6}-${fld7}${suffix}"
echo "moving ${path}/${fn} to ${path}/${newfn}"
mv ${path}/${fn} ${path}/${newfn}"
}
export -f modfn
suffix="-all.mp3"
export suffix
find . -type f -name "*${suffix}" ! -name "*-*${suffix}" -exec bash -c 'modfn "$0" ${suffix}' {} +
The above bash script uses find to search in the current folder and it's contents for files like WWW_XXXX_YYYYYYYYYY_AAAAAABBBBBB-all.mp3 yet excludes ones that are already renamed and look like WWW_XXXX_YYYYYYYYYY_20AAAAAA-BBBBBB-all.mp3.
W,X,Y,A,B can be any character other than underscore or dash.
All the found files are renamed
NOTE: There are ways to shrink the above script but doing that makes the operation less obvious.
This perl one-liner does the job:
find . -name "XXX_XXXX_YYYYYYYYYY_*-all.mp3" -printf '%P\n' 2>/dev/null | perl -nle '$o=$_; s/_[0-9]{6}/_20100426-/; $n=$_; rename($o,$n)if!-e$n'
Note: I came just with a find command and regex part. The credit for a perl one liner goes to perlmonks user at http://www.perlmonks.org/?node=823355

How to use awk's output on bash command line

I have a file named "01 - Welcome To The Jungle.mp3", and I want to do eyeD3 -t "Welcome To the Jungle" 01 - Welcome To The Jungle.mp3 to modify the tag of the all the files in the folder. I've extracted from the file with awk: "Welcome To The Jungle" doing:
#!/bin/bash
for i in *.mp3
do
eyeD3 -t $(echo ${i} | awk -F' - ' '{print $2}' | awk -F'.' '{print $1}') ${i}
done
It doesn't work. Neither the whole "$(echo S{i}....)" nor the "${i}" seem to work for replacing the names of the respective files.
You need to prevent word splitting on IFS (default: space, tab, newline) by shell, as your input filename contains space(s). The typical workaround is to use double quotes around the variable expansion.
Do:
for i in *.mp3; do eyeD3 -t "$(echo "$i")" | ...; done
You can leverage here string, <<<, to avoid the echo-ing:
for i in *.mp3; do eyeD3 -t <<<"$i" | ...; done
You need to double-quote variables that may contain spaces, as #heemayl already pointed out.
Also, in this example, instead of using awk,
it would be better to use native Bash pattern substitution to extract the title, for example:
for file in *.mp3; do
title=${file%.mp3}
title=${title#?????}
eyeD3 -t "$title" "$file"
done
That is:
Remove .mp3 at the end
Remove the first 5 characters (the count prefix NN -)

How to store in a variable an echo | cut result?

for example
echo "filename.pdf" | cut -d'.' -f 1
This way I get the "filename" string.
I'd like to store it in a variable called FILE and then use it like this:
DIR=$PATH/$FILE.txt
So, my script wants to create a file.txt with the same name of the pdf (not a copy of the file, just the name)
This way I tried to assign the result of echo | cut
FILE=
but I get only "path/.txt" so the filename is missing.
FILE=$(echo "filename.pdf" | cut -d'.' -f 1)
So, my script wants to create a file.txt with the same name of the pdf
You can use BASH string manipulation:
s="filename.pdf"
p="${s/%.pdf/.txt}"
echo "$p"
filename.txt
POSIX parameter expansion would read
file=filename.pdf
filename="${file%%.*}" # Two % will remove multiple extensions, if applicable
dir=$path/$filename.txt

Output result of grep to var then to system file

There is a parameter that I need to grep from a file and then I need to get that parameter into another file. I need to read the variable at boot time and have it inserted in
$grep "id" /file/one | cut -d " " -f2
$12345
So now I have the ID_VAR of 12345. Now what I would like to do is use this in /file/two
In file/two:
...
#program ID_VAR
...
Is there a way to run the grep function inside file two? Is there a way to share a variable between files? I am using Debian.
grep an id from one file and append to another file prepended with the string #program:
echo '#program' $(grep "id" file/one | cut -d " " -f2) >> file/two
There are some ambiguities in your question, but I think this snippet of script is what you are looking for:
Assuming #program is already in your file 2: (otherwise, see sudo_o's solution)
ID_VAR=$(grep "id" /file/one | cut -d " " -f2)
sed -i "s/#program/#program ${ID_VAR}/" /file/two
Explanation:
ID_VAR=$(...): save of the result of your grep and cut into ID_VAR
sed: invoke sed and use the -i option to edit the input file in place
"s/#program/#program ${ID_VAR}/": replace #program with #program (value of ID_VAR) in the input file
/file/two: what your input file is

Resources