Unable to read user input inside a loop

Hi,

This query is a part of a much more lengthy script.

I wish to look for all the files in a folder named "data" which in this case has two files i.e. plan.war and agent.properties . For all the files found under data I wish to ask the user as to where they wish copy the files to.

Below, is my script for the same.

more run.sh
 #!/bin/bash
 cd data
find . -type f \! -name test.tar | $AWK -F/ '{print $NF}' | while IFS= read -r entry; do
 echo "FILE_CURRENT_DIR:"$entry
 read -p 'Where do you want to copy $entry to? Please enter the complete directory location: ' cppath
echo "cp -R $entry $cppath/"
cp -R $entry $cppath/
 done

However, instead of asking me for input the script considers the second file found under data folder at the target location for the copy and thus fails.

Kindly see the problematic output below.

Can you please help me get user prompt for every file found under data ?

You have two read , so you have to use a different file descriptor to make it work.

Another approach is to use a for loop instead:-

for file in data/*
do
        [[ "$file" =~ "test.tar" ]] && continue;

        read -p "Where do you want to copy ${file} to? enter absolute path: " cp_path

        echo "cp -R $file ${cp_path}/"
done
1 Like

Can you please give me an example for this approach ?

Also, if i use your code how can i include wow.tar along with test.tar ?

I mean test.tar or wow.tar if either is found do not consider them.

Thank you.

Can you please give me an example for this approach ?

CWD=$(pwd)
find data/ -type f \! -name test.tar | $AWK -F/ '{print $NF}' > ${CWD}/out.txt

while read entry
do
        echo "FILE_CURRENT_DIR:"$entry
        read -p 'Where do you want to copy $entry to? Please enter the complete directory location: ' -u 3 cppath
        echo "cp -R $entry $cppath/"
done 3<&0 < ${CWD}/out.txt
if [[ "$file" =~ "test.tar" ]] || [[ "$file" =~ "wow.tar" ]]
then
        continue
fi
1 Like

Thank you; I will try these out tonight and let you know if they work realtime.

---------- Post updated at 11:56 AM ---------- Previous update was at 11:40 AM ----------

The files may not be in the data folder instead in its sub-directories.

Can you please confirm if replacing the find with for will still work as you suggested ?

Replacing find with for will not traverse sub-directories. Use the find based approach if you want to traverse sub-directories and work on files in them.

You can keep the pipe if you redirect the whole block.

{
find data/ -type f \! -name test.tar | $AWK -F/ '{print $NF}' |
 while IFS= read -r entry
 do
        echo "FILE_CURRENT_DIR:$entry"
        printf "Where do you want to copy '$entry' to? Please enter the complete directory location: "
        read cppath <&3
        echo cp "$entry" "$cppath/"
 done
} 3<&0

<&3 lets the shell do what read does with -u 3.
read -p "text" is bash-only. Portable is printf "text"; read .

Can you please tell me why is it failing when I try the same.

#!/bin/ksh
 . ./deploy.profile
set -x
found_flag=0
 searchdir=/tmp/moht
 CWD=$(pwd)
 
 find $searchdir"/PRESENT/data" -type f \! -name client.tar | $AWK -F/ '{print $NF}'  > ${CWD}/out.txt
 while IFS= read -r entry; do
  found_flag=0
if [ $found_flag -eq 0 ]; then
read -p "Where do you want to copy $entry to? Please enter the complete directory location: " -u 3 cppath
echo "cp -R $entry $cppath/"
cp -R $entry $cppath/
fi
  echo "Displaying the value of found_flag outside while loop:$found_flag"
 done 3<&0 < ${CWD}/out.txt

Error:

Hope this works with the KSH shell as well. Does it ?

read is a shell built-in. The KSH built-in has different options to the Bash one. Is there any reason you changed your script from Bash to the Korn shell?

The reason for changing to KSH from BASH was my bash version is 10 yrs old and I cannot update it as I m not the system admin. I need my variable to hold global value so it persists its value outside the loop. Refer to my thread here for details.

Can you propose any solution to the error I m getting as shown in RED BOLD this POST 8.

You should at-least check the ksh manual, look at the read options and give it a try before posting question:-

man ksh

       read [ -ACprsv ] [ -d delim] [ -n n] [ [ -N n] [ [ -t timeout] [ -u unit] [ vname?prompt ] [ vname ... ]

So you should modify your code to:-

read -u 3 cppath?"Where do you want to copy $entry to? Please enter the complete directory location: "

I tried that but it gives me this error:

+ read -u 3?cppath Where do you want to copy bingo.txt to? Please enter the complete directory location:
./readtest.sh[25]: 3: is not an identifier

My ksh man page says:

     read [ -prsu[ n ] ] [ name?prompt ] [ name ... ]

I noticed the ? symbol right after the descriptor instead of variable name:-

+ read -u 3?cppath Where do you want to copy bingo.txt to? Please enter the complete directory location:
./readtest.sh[25]: 3: is not an identifier

Also you need to check your ksh version and manual for read options, I tested this code in ksh93 and it works fine:-

$ strings /bin/ksh | grep "[V]ersion"
@(#)$Id: Version AJM 93t+ 2010-06-21 $

My ksh version is:

strings /bin/ksh | grep "[V]ersion"
@(#)Version M-11/16/88i

the variable name is cppath.

I tried

read -u 3 cppath "Where do you want to copy $entry to? Please enter the complete directory location: "

but this also fails with the same error : 3: is not an identifier . Can you tell me what syntax should I try ?

With 779 posts and 6-odd years on this forum (and working on scripts in general), I can't believe you can't figure out how to use the read command.

I really don't sense that you have the will to learn anything from us, so this thread is closed.

2 Likes