开发者

Bash prepending backtick to string

Bash keeps on adding a ` right before $corrected on the myStats line. How do I get rid of it?

A little background: I created a script to loop through files given in search.txt to give stats on and output them into a new file. It worked fine, but it broke on any file name that had a space in the directory or file, so I needed to add quotes to the file path.

For some reason, adding quotes to the file path creates a ` at the beginning of the path, rendering the entire script useless. Substringing $corrected did not help, the ` is being added on the myStats line.

for i in $(cat search.txt); do
    corrected=\"$( echo "$i" )\"
    echo $corrected
    myStats="`stat $corrected | awk '( NR == 1 ) {print $1 $2 $3 $4 $5 $6 $7 $8};\
        ( NR == 2 ) {print $1 $2};\
        ( NR == 4 ) {print $3 $4 $5 $6 " " $7 $8 $9 $10 };\
        ( NR == 6 ) {print $1 $2 " " $3};'`"
    echo $myStats >> "$myHostname"
done

A sample from search.txt:

/var/lib/tomcat5/webapps/isp.bak/usa.css
/var/lib/tomcat5/webapps/isp.bak/validationFunctions.js

Anybody have any ideas? Thanks!

Edit: I0b0 gave an excellent solution, and I also learned about IFS from everybody. Sorry about not including output, it completely slipped my mind. Here is my updated code (much more condensed now), whose function is to find these file extensions to see what I need to back up on the server.

#Get file name as hostnameFiles.txt
myHostname="$(hostname)Files.txt"

#Write initial information to file
uname -n > "$myHostname"
开发者_开发知识库echo "Script run on: " >> "$myHostname"
date -u >> "$myHostname"
echo "" >> "$myHostname"

#For each line from find, run stat and pull relevant information.
while IFS= read -r; do
    #echo "$REPLY"
    echo "$(stat "$REPLY" | awk '( NR == 1 ) {print $1 $2 $3 $4 $5 $6 $7 $8};\
        ( NR == 2 ) {print $1 $2};\
        ( NR == 4 ) {print $3 $4 $5 $6 " " $7 $8 $9 $10 };\
        ( NR == 6 ) {print $1 $2 " " $3};')" >> "$myHostname"
done < <(find / -iname "*.css" -or -iname "*.html" -or -iname "*.java" -or -iname "*.js" -or -iname "*.jsp" -or -iname "*.php" -or -iname "*.pl" -or -iname "*.py" -or -iname "*.rb"  -or -iname "*.sql")

Thanks again, guys, all of your input was very useful for a newbie!


Here's a simple solution:

while IFS= read -r; do
    echo "$REPLY"
    echo "$(stat "$REPLY" | awk '( NR == 1 ) {print $1 $2 $3 $4 $5 $6 $7 $8};\
        ( NR == 2 ) {print $1 $2};\
        ( NR == 4 ) {print $3 $4 $5 $6 " " $7 $8 $9 $10 };\
        ( NR == 6 ) {print $1 $2 " " $3};')" >> "$myHostname"
done < search.txt

If you want to do this without the temporary search.txt file, simply replace the last line done < <(find ...)

The backtick before the file name is easily explained if you look at the output of a simple touch 'foo bar' && stat 'foo bar' - The file line is quoted in the stat output. You should modify the awk script to include all the line instead of just concatenating the columns, and to remove the start and end quotes if the file name contains anything which will result in quotes.


There are numerous syntax/usage errors with your string and variable quoting that can easily account for the issues you have identified. If you care to edit your question, it would be helpful to see the actual input and the error output that you are getting.

Anyway, uou need to escape the " chars in your awk print statements, i.e.

savIFS=${IFS}
IFS=
for i in $(cat search.txt); do
    corrected=\"$( echo "$i" )\"
    echo $corrected
    myStats="$(
        stat "$corrected" \
        | awk '
        ( NR == 1 ) {print $1 $2 $3 $4 $5 $6 $7 $8};
        ( NR == 2 ) {print $1 $2};
        ( NR == 4 ) {print $3 $4 $5 $6 \" \" $7 $8 $9 $10 };
        ( NR == 6 ) {print $1 $2 \" \" $3}
        '
      )"   # end myStats
    echo "$myStats" >> "$myHostname"
done
IFS="${savIFS} ; unset savIFS

I also recommend that you replace backtics command substitution with $(...) as you use for the cat search.txt in the for loop. You're using $(...) several other places, why not where it can really help you, with a multi-line bit of code.

I assume you don't want to lose the formatting of $myStats, and so I have surrounded that with dbl-quotes. In general, all variable references, i.e. $corrected, should be surrounded in dbl-quotes.

Its hard to be sure if I have this right, as I don't have the time to create test files with spaces in the names and make a new search.txt, but I'll be happy to work with you if there are errors when running this code. The ${IFS} may be unnecessary, but again my time has almost run out.

I hope this helps.

P.S. as you appear to be a new user, if you get an answer that helps you please remember to mark it as accepted, and/or give it a + (or -) as a useful answer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜