Shell no such file or directory - linux

While trying to run a for loop in shell I encountered a problem.
for i in `cat $file`
do
`cut -d ',' -f 2- $i`
done
I tried to cut the lines from the second column and output them, however it gave me an error: (content of the file) no such file or directory

First, you try to execute the output of the cut command.
Consider:
$ echo hello >file
$ cat file
hello
$ a=`cat file`
$ echo "$a"
hello
$ `echo "$a"`
-bash: hello: not found
$
Perhaps you just wanted to display the output of cut:
for i in `cat "$file"`
do
cut -d , -f 2- $i
done
Second, you pass cut an argument that is expected to be a filename.
You read data from $file and use it as a filename. Is that data actually a filename?
Consider:
$ echo a,b,c,d >file
$ cat file
a,b,c,d
$ a=`cat file`
$ echo "$a"
a,b,c,d
$ cut -d , -f 2- file
b,c,d
$ cut -d , -f 2- "$a"
cut: a,b,c,d: No such file or directory
Perhaps you wanted:
cut -d , -f 2- "$file"
Thirdly, your for loop splits the data in "$file" on whitespace, not by line.
Consider:
$ echo 'a b,c d' >file
$ cat file
a b,c d
$ for i in `cat file`; do echo "[$i]"; done
[a]
[b,c]
[d]
$
Perhaps you wanted to read individual lines?
while read i; do
: ...
done <file

Related

How to rename a file that starts with a sequence using bash command line

I have multiple files in a folder that i want to rename. The file names are currently in the below format.
axuajsnd_file1.txt
asdeacasasacas_file2.txt
What i am trying to do is rename all these files to the name after the underscore, so axuajsnd_file1.txt would be file1.txt.
Can i do this using a single line command or would i need a script to rename all my files?
With a for loop , Parameter Expansion and mv.
for f in *_*.txt; do echo mv -v "$f" "${f#*_}"; done
Remove the echo if you're satisfied with the output, so mv can move/rename the files.
Let's say you have:
$ ls
axuajsnd_file1.txt
asdeacasasacas_file2.txt
sdmsdmksdmsddsms_file3.txt
skdksdksdkmdskm_file4.txt
Check that the result is correct:
$ for i in *.txt; do echo "$i -> $(echo $i | awk -F '_' '{print $2}')"; done
asdeacasasacas_file2.txt -> file2.txt
axuajsnd_file1.txt -> file1.txt
sdmsdmksdmsddsms_file3.txt -> file3.txt
skdksdksdkmdskm_file4.txt -> file4.txt
Now that you checked, you may rename your files:
$ for i in *.txt; do mv "$i" $(echo "$i" | awk -F '_' '{print $2}'); done
Output:
$ ls
file1.txt file2.txt file3.txt file4.txt

Extract left and right from filename based on last delimiter using shell script

I would like to extract left and right from filename based on last delimiter using shell script
Ex : filename = 'test_testone_test3_1234'
I'm expecting below values
file = 'test_testone_test3'
seq = '1234'
Is there a better approach to do it ?
You may want to learn a little bit about Parameter Expansion
$ filename="test_testone_test3_1234"
$ echo "${filename#*_}"
testone_test3_1234
$ echo "${filename##*_}"
1234
$ echo "${filename%_*}"
test_testone_test3
$ echo "${filename%%_*}"
test
$ echo "${filename#*_*_}"
test3_1234
$ echo "${filename%_*_*}"
test_testone
You can also use cut.-d is for field separator and -f for the fields.
$ filename="test_testone_test3_1234"
$ echo "$filename" | cut -d_ -f1-3
test_testone_test3
$ echo "$filename" | cut -d_ -f4
1234
$ echo "$filename" | cut -d_ -f1-2
test_testone
$ echo "$filename" | cut -d_ -f3-
test3_1234

Unix: replace variable in file a with value in file b

I have two files in Linux, in file a there are variables like these:
${VERSION} ${SOFTWARE_PRODUCER}
And the values of these variables are stored in file b:
VERSION=1.0.1
SOFTWARE_PRODUCER=Luc
Now how can I use command to replace the variables in file a with values in file b? Is something like sed able to do this task?
Thanks.
A simple bash loop would suffice:
$ cat a
This is file 'a' which has this variable ${VERSION}
and it has this also:
${SOFTWARE_PRODUCER}
$ cat b
VERSION=1.0.1
SOFTWARE_PRODUCER=Luc
$ cat script.bash
#!/bin/bash
while read line || [[ -n "$line" ]]
do
key=$(awk -F= '{print $1}' <<< "$line")
value=$(awk -F= '{print $2}' <<< "$line")
sed -i 's/${'"$key"'}/'"$value"'/g' a
done < b
$ ./script.bash
$ cat a
This is file 'a' which has this variable 1.0.1
and it has this also:
Luc
$

how to extract grep and cut into a bash array

I tried:
here is content of file.txt
some other text
#1.something1=kjfk
#2.something2=dfkjdk
#3.something3=3232
some other text
bash script:
ids=( `grep "something" file.txt | cut -d'.' -f1` )
for id in "${ids[#]}"; do
echo $id
done
result:
(nothing newline...)
(nothing newline...)
(nothing newline...)
but all it prints is nothing like newline for every such id found what am i missing?
Your grep and cut should be working but you can use awk and reduce 2 commands into one:
while read -r id;
echo "$id"
done < <(awk -F '\\.' '/something/{print $1}' file.txt)
To populate an array:
ids=()
while read -r id;
ids+=( "$id" )
done < <(awk -F '\\.' '/something/{print $1}' file.txt)
You can use grep's -o option to output only the text matched by a regular expression:
$ ids=($(grep -Eo '^#[0-9]+' file.txt))
$ echo ${ids[#]}
#1 #2 #3
This of course doesn't check for the existence of a period on the line... If that's important, then you could either expand things with another pipe:
$ ids=($(grep -Eo '^#[0-9]+\.something' file.txt | grep -o '^#[0-9]*'))
or you could trim the array values after populating the array:
$ ids=($(grep -Eo '^#[0-9]+\.something' file.txt))
$ echo ${ids[#]}
#1.something #2.something #3.something
$ for key in "${!ids[#]}"; do ids[key]="${ids[key]%.*}"; done
$ echo ${ids[#]}
#1 #2 #3

Length of shortest line?

In Linux command using wc -L it's possible to get the length of longest line of a text file.
How do I find the length of the shortest line of a text file?
Try this:
awk '{print length}' <your_file> | sort -n | head -n1
This command gets lengths of all files, sorts them (correctly, as numbers) and, fianlly, prints the smallest number to console.
Pure awk solution:
awk '(NR==1||length<shortest){shortest=length} END {print shortest}' file
I turned the awk command into a function (for bash):
function shortest() { awk '(NR==1||length<shortest){shortest=length} END {print shortest}' $1 ;} ## report the length of the shortest line in a file
Added this to my .bashrc (and then "source .bashrc" )
and then ran it: shortest "yourFileNameHere"
[~]$ shortest .history
2
It can be assigned to a variable (Note the backtics are required):
[~]$ var1=`shortest .history`
[~]$ echo $var1
2
For csh:
alias shortest "awk '(NR==1||length<shortest){shortest=length} END {print shortest}' \!:1 "
Both awk solutions from above do not handle '\r' the way wc -L does.
For a single line input file they should not produce values greater than maximal line length reported by wc -L.
This is a new sed based solution (I was not able to shorten while keeping correct):
echo $((`sed 'y/\r/\n/' file|sed 's/./#/g'|sort|head -1|wc --bytes`-1))
Here are some samples, showing '\r' claim and demonstrating sed solution:
$ echo -ne "\rABC\r\n" > file
$ wc -L file
3 file
$ awk '{print length}' file|sort -n|head -n1
5
$ awk '(NR==1||length<shortest){shortest=length} END {print shortest}' file
5
$ echo $((`sed 'y/\r/\n/' file|sed 's/./#/g'|sort|head -1|wc --bytes`-1))
0
$
$ echo -ne "\r\r\n" > file
$ wc -L file
0 file
$ echo $((`sed 'y/\r/\n/' file|sed 's/./#/g'|sort|head -1|wc --bytes`-1))
0
$
$ echo -ne "ABC\nD\nEF\n" > file
$ echo $((`sed 'y/\r/\n/' file|sed 's/./#/g'|sort|head -1|wc --bytes`-1))
1
$

Resources