0

In my bash, the whole script won't work... When I use `

My script is

#!/bin/bash

yesterday=$(date --date "$c days ago" +%F)

while IFS= read -r line
do

dir=$(echo $line | awk -F, '{print $1 }')
country=$(echo $line | awk -F, '{print $2 }')

cd path/$dir

cat `ls -v | grep email.csv` > e.csv 

done < "s.csv"

Above output is blank.

If i use ""

output is No such file or directory

but if I use only 1 line on the terminal it works

cat `ls -v | grep email.csv` > e.csv 

I also try with / , but didnt work either...

Pierre François
  • 5,850
  • 1
  • 17
  • 38
Amit Singh
  • 188
  • 9
  • Copy/paste your code into http://shellcheck.net, fix the issues it tells you about, and then let us know if you still have a problem and post the corrected code. – Ed Morton May 05 '21 at 14:18

1 Answers1

3

You should generally avoid ls in scripts.

Also, you should generally prefer the modern POSIX $(command substitution) syntax like you already do in several other places in your script; the obsolescent backtick `command substitution` syntax is clunky and somewhat more error-prone.

If this works in the current directory but fails in others, it means that you have a file matching the regex in the current directory, but not in the other directory.

Anyway, the idiomatic way to do what you appear to be attempting is simply

cat *email?csv* >e.csv

If you meant to match a literal dot, that's \. in a regular expression. The ? is a literal interpretation of what your grep actually did; but in the following, I will assume you actually meant to match *email.csv* (or in fact probably even *email.csv without a trailing wildcard).

If you want to check if there are any files, and avoid creating e.csv if not, that's slightly tricky; maybe try

for file in *email.csv*; do
    test -e "$file" || break
    cat *email.csv* >e.csv
    break
done

Alternatively, look into the nullglob feature of Bash. See also Check if a file exists with wildcard in shell script.

On the other hand, if you just want to check whether email.csv exists, without a wildcard, that's easy:

if [ -e email.csv ]; then
    cat email.csv >e.csv
fi

In fact, that can even be abbreviated down to

test -e email.csv && cat email.csv >e.csv

As an aside, read can perfectly well split a line into tokens.

#!/bin/bash

yesterday=$(date --date "$c days ago" +%F)

while IFS=, read -r dir country _
do
    cd "path/$dir"   # notice proper quoting, too
    cat *email.csv* > e.csv
    # probably don't forget to cd back
    cd ../..
done < "s.csv"

If this is in fact all your script does, probably do away with the silly and slightly error-prone cd;

while IFS=, read -r dir country _
do
    cat "path/$dir/"*email.csv* > "path/$dir/e.csv"
done < "s.csv"

See also When to wrap quotes around a shell variable.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • I was joking... The actual code is too long.. If i change here with ls, i need to make many changes... but the one using break is new to me... in loop i never do cd back. becaue each time loop run i 1st enter in dircetory by full path... – Amit Singh May 05 '21 at 08:58
  • If you want to check for the literal file name `email.csv` without the need for any wildcards, that's a lot easier; see updated answer now. See also the note about entirely avoiding `cd` near the end. – tripleee May 05 '21 at 09:00