Ls command in a for loop displaying error

I have a few files inside a directory and in my code i am listing the files to get the filenames and do further operations.Details are given below:
Dirname is taken as argument in $3 and filenames in variable $file

Directory name =$3= /tmp/to-be_parsed/input
Filename= $file= JAN_DAT_TES1_201807181400.csv
                 J       JAN_DAT_TES2_201807181400.csv

The code i wrote is


for i in `ls $3/$file|cut -d'/' -f5`
do
mv ......
........
..........
done	

When i run the script,it says

ls: /tmp/to-be_parsed/input/JAN_DAT_TES1_201807181400.csv:No such file or directory
ls: /tmp/to-be_parsed/input/JAN_DAT_TES2_201807181400.csv:No such file or directory

Files are present in the directory.I am not able to figure out why the ls command says no files.Could you pl. help me with this to correct the mistake

Look like your count is wrong (I may be wrong still half asleep...) I count 4 => so it should be -f4

Thank you. I changed it to -f4 but still it shows the same error :frowning:

it only works with field 5

for i in `ls $3/$file|cut -d'/' -f5`

do so

for i in $(ls $3/$file | xargs basename -a)

--- Post updated at 10:30 ---

I think you have not correctly defined the variable $file. Try this

echo $3/$file

much better indeed but why use any external utility when the shell can do the same:

for i in $(ls "${3}/${file}") ; do
     i="${i##*/}"

The only way this is going to break is if the filename has newlines embedded.

I hope this helps.

bakunin

3 Likes

I would also replace this construction

for i in ${3}/$file ; do
     i="${i##*/}"
3 Likes

I wonder what the purpose of the loop is.
Do you want to search and loop over the found files?
Then use a glob search! For example

for pfn in "$3"/JAN_DAT_TES*.csv
do
  # the shell puts the glob pattern if there was no match, so ensure that the file exists
  [ -f "$pfn" ] || continue
  # fn=basename(pfn) achieved with a builtin modifier
  fn=${pfn##*/}
  echo "do something with $pfn or $fn"
done
2 Likes

(1) As nezabudka says, try this:

echo $3/$file

But also:

file $3/$file

or:

test -e $3/$file && echo $3/$file exists

I would guess that either the directory ($3) is missing a component (i.e. should it be /tmp/to-be_parsed/input/JAN ?) or it's mis-typed (i.e. should it be /tmp/to-be-parsed/input ?)

(2) What is the point of

for in in $(ls $dir/$file)

if $dir and $file have no wild cards? You might as well be doing:

for i in $(ls /usr/bin/at)

or

for i in one

In other words you have a for loop around a single file.

(3) Don't use backticks (`...`) for process substitution - use $(...) . It is easier to read, allows for embedding one process substitution in another, and, unless you are using a really old shell like the one in Solaris, is recognised by all shells.

Andrew

Do you risk having spaces, tab or other naughty characters in the directory name or file name? You would be safer to use "${3}/${file}" to ensure that the values are treated as a single item. if you have a for loop on items with spaces, then they will be split up and processed separately. For instance:-

whole_message="Hello world"
for one_message in ${whole_message}
do
   echo ${one_message}
done
Hello                                          # <---- Output split to one
world.                                         # <---- line for word

whole_message="Hello world"
for one_message in "${whole_message}"          # <--- Wrapped in double quotes
do
   echo ${one_message}
done
Hello world                                    # <---- Output for one value all written as one line.

I hope that this helps,
Robin

1 Like