baguiar428
baguiar428

Reputation: 15

While loop in Bash script removing first line when reading from file

I'm trying to pass a file into a script which will take each line and convert it to be compatible with Mac. It does that by sed'ing the line and then cutting out relevant information and putting it into a variable to be used later. So if a line in the source file is: windows_cmd \ip.address\sharename\rest\of\path "\download\location"

Sed will remove everything in-between the "" then convert the "\" to "/". Afterwards I want to use the "/" as a delimiter to cut out relevant info like server_ip, share_name and etc.

Whenever the while loop runs through it always skips the first line in the file AND I can't get my script to output the variables so i can troubleshoot.

xcopy /y  \\111.22.3.444\DATA\400221\800\4002218002360 "~/desktop\4002218002360\"
xcopy /y  \\111.22.3.444\DATA\612608\807\612608807228 "~/desktop\612608807228\"
xcopy /y  \\111.22.3.444\DATA\194491\126\194491126025 "~/desktop\194491126025\"

My source file looks like:

#!/bin/bash

input_file="$1"

while read i; 
    do sed s/\".*$// | sed s/'\\'/'\/'/g;
        export SERVER_NAME=$(echo "$i" | cut -d / -f 4); 
        export SHARE_NAME=$(echo "$i" | cut -d / -f 5);
    done < $1

    echo ${SERVER_NAME}
    echo ${SHARE_NAME}
exit 0

I expected an output of :

xcopy /y  //111.22.3.444/DATA/400221/800/4002218002360
xcopy /y  //111.22.3.444/DATA/612608/807/612608807228
xcopy /y  //111.22.3.444/DATA/194491/126/194491126025

But instead i get :

xcopy /y  //111.22.3.444/DATA/612608/807/612608807228
xcopy /y  //111.22.3.444/DATA/194491/126/194491126025

<2 blank lines>

Upvotes: 0

Views: 649

Answers (2)

webb
webb

Reputation: 4340

Why not give awk a try?

#!/bin/bash

input_file="$1"

# change all \ to / in the third column of input text:
awk '{gsub(/\\/,"/",$3);print}' $input_file

# change the fourth column, too:
awk '{gsub(/\\/,"/",$3);gsub(/\\/,"/",$4);print}' $input_file

Also, once you have code the produces all of the correct command strings, you can directly pipe to bash to run them one-by-one, e.g.,

awk '{gsub(/\\/,"/",$3);gsub(/\\/,"/",$4);print}' $input_file | bash

...but make sure the commands are correct first before adding the | bash.

Upvotes: 0

William Pursell
William Pursell

Reputation: 212198

Your loop is poorly constructed. For analysis, let's simplify it to:

while read i; do 
   sed cmd
done < $1

read reads one line of the input file. Then sed is started, inheriting its stdin from the loop. Since the first line of data has already been consumed, sed starts reading at the second line. It consumes all of the data and exits. Then read is executed again, and returns non-zero (since there's no data left). What is the purpose of the while read loop?

I think what you're trying to do can be accomplished with:

< $1 sed ... |
while IFS=/ read a b c SERVER_NAME SHARE_NAME; do
    echo ${SERVER_NAME}
    echo ${SHARE_NAME}
done

But it seems like it would be cleaner to do:

awk '{print $3}' $1 |
while IFS=\\ read a b c SERVER_NAME SHARE_NAME; do 
    echo $SERVER_NAME
    echo $SHARE_NAME
done

Upvotes: 1

Related Questions