PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Forums Hébergement > Forum Serveur - Sécurité et techniques > comp.unix.shell > Bash: Strange quoting in pipelined commands
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
comp.unix.shell Using and programming the Unix shell.

Bash: Strange quoting in pipelined commands

Réponse
 
LinkBack Outils de la discussion
Vieux 25/07/2007, 22h55   #1
Mister.Fred.Ma@gmail.com
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Bash: Strange quoting in pipelined commands

I have the following files/subdirectories listed in List.txt.

$cat List.txt

FixDiff.out
Temp.txt
diff.out
dog &cat

There are no leading or trailing spaces on each line. I want to
submit this to "find" after quoting each line. This command seems to
do the quoting:

cat List.txt | sed -e 's/.*/"&"/'

It generates:

"FixDiff.out"
"Temp.txt"
"diff.out"
"dog &cat"

Here is how I fed it to the "find" command. The head command simply
ensures that I don't pollute the display with "find" output, and that
no time is wasted on the find command, thus enabling me to quickly see
the expanded command from "set -x".

set -x
find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0
find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0
find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0

Here is the output:

$ find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0

find '"' 'FixDiff.out"' '"' 'Temp.txt"' '"' 'diff.out"' '"' dog
'&cat"' -type f

$ find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0

find FixDiff.out Temp.txt diff.out dog '&cat' -type f

$ find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0

find ''\''' 'FixDiff.out'\''' ''\''' 'Temp.txt'\''' ''\'''
'diff.out'\''' ''\''' dog '&cat'\''' -type f

The 1st "find" is what I expected to work, but it generates extra
single-quotes. The 2nd "find" is a debugging step to find out exactly
what happens when the 4-line output of "cat | sed" is put onto a
single physical line for "find". Apparently, spaces are not
protected, though ampersands are. Leading quotes are protected, but
are considered separated out as distinct arguments.

The above is just a illustration of this behaviour. The actual usage
involves grepping a file instead of cat'ing it. The result is even
stranger -- using the 1st "find" above, only the 1st 2 filenames
contain quotes (wrong though they may be), while the remaining large
number of filenames have not quoting at all.

Is there a way to generate the required quoting? I realize I can
prepend backslashes to all nonstandard characters, but simply quoting
the whole thing seemed alot simpler than identifying all nonstandard
characters -- if it can be made to work.

Why do the above 3 "find" commands generate such strange quoting?

Thanks!

  Réponse avec citation
Vieux 25/07/2007, 23h14   #2
Michael Tosch
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Bash: Strange quoting in pipelined commands

Mister.Fred.Ma@gmail.com wrote:
> I have the following files/subdirectories listed in List.txt.
>
> $cat List.txt
>
> FixDiff.out
> Temp.txt
> diff.out
> dog &cat
>
> There are no leading or trailing spaces on each line. I want to
> submit this to "find" after quoting each line. This command seems to
> do the quoting:
>
> cat List.txt | sed -e 's/.*/"&"/'
>
> It generates:
>
> "FixDiff.out"
> "Temp.txt"
> "diff.out"
> "dog &cat"
>
> Here is how I fed it to the "find" command. The head command simply
> ensures that I don't pollute the display with "find" output, and that
> no time is wasted on the find command, thus enabling me to quickly see
> the expanded command from "set -x".
>
> set -x
> find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0
> find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0
> find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0
>
> Here is the output:
>
> $ find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0
>
> find '"' 'FixDiff.out"' '"' 'Temp.txt"' '"' 'diff.out"' '"' dog
> '&cat"' -type f
>
> $ find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0
>
> find FixDiff.out Temp.txt diff.out dog '&cat' -type f
>
> $ find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0
>
> find ''\''' 'FixDiff.out'\''' ''\''' 'Temp.txt'\''' ''\'''
> 'diff.out'\''' ''\''' dog '&cat'\''' -type f
>
> The 1st "find" is what I expected to work, but it generates extra
> single-quotes. The 2nd "find" is a debugging step to find out exactly
> what happens when the 4-line output of "cat | sed" is put onto a
> single physical line for "find". Apparently, spaces are not
> protected, though ampersands are. Leading quotes are protected, but
> are considered separated out as distinct arguments.
>
> The above is just a illustration of this behaviour. The actual usage
> involves grepping a file instead of cat'ing it. The result is even
> stranger -- using the 1st "find" above, only the 1st 2 filenames
> contain quotes (wrong though they may be), while the remaining large
> number of filenames have not quoting at all.
>
> Is there a way to generate the required quoting? I realize I can
> prepend backslashes to all nonstandard characters, but simply quoting
> the whole thing seemed alot simpler than identifying all nonstandard
> characters -- if it can be made to work.
>
> Why do the above 3 "find" commands generate such strange quoting?
>
> Thanks!
>


The `` generates a list of IFS-separated tokens.
It is safer to read the file line by line,
and each time run a find command:

while read -r line
do
find "$line" ...
done < List.txt


--
Michael Tosch @ hp : com
  Réponse avec citation
Vieux 25/07/2007, 23h57   #3
Mister.Fred.Ma@gmail.com
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Bash: Strange quoting in pipelined commands

On Jul 25, 6:14 pm, Michael Tosch <eed...@NO.eed.SPAM.ericsson.PLS.se>
wrote:
> Mister.Fred...@gmail.com wrote:
> > I have the following files/subdirectories listed in List.txt.

>
> > $cat List.txt

>
> > FixDiff.out
> > Temp.txt
> > diff.out
> > dog &cat

>
> > There are no leading or trailing spaces on each line. I want to
> > submit this to "find" after quoting each line. This command seems to
> > do the quoting:

>
> > cat List.txt | sed -e 's/.*/"&"/'

>
> > It generates:

>
> > "FixDiff.out"
> > "Temp.txt"
> > "diff.out"
> > "dog &cat"

>
> > Here is how I fed it to the "find" command. The head command simply
> > ensures that I don't pollute the display with "find" output, and that
> > no time is wasted on the find command, thus enabling me to quickly see
> > the expanded command from "set -x".

>
> > set -x
> > find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0
> > find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0
> > find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0

>
> > Here is the output:

>
> > $ find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0

>
> > find '"' 'FixDiff.out"' '"' 'Temp.txt"' '"' 'diff.out"' '"' dog
> > '&cat"' -type f

>
> > $ find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0

>
> > find FixDiff.out Temp.txt diff.out dog '&cat' -type f

>
> > $ find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0

>
> > find ''\''' 'FixDiff.out'\''' ''\''' 'Temp.txt'\''' ''\'''
> > 'diff.out'\''' ''\''' dog '&cat'\''' -type f

>
> > The 1st "find" is what I expected to work, but it generates extra
> > single-quotes. The 2nd "find" is a debugging step to find out exactly
> > what happens when the 4-line output of "cat | sed" is put onto a
> > single physical line for "find". Apparently, spaces are not
> > protected, though ampersands are. Leading quotes are protected, but
> > are considered separated out as distinct arguments.

>
> > The above is just a illustration of this behaviour. The actual usage
> > involves grepping a file instead of cat'ing it. The result is even
> > stranger -- using the 1st "find" above, only the 1st 2 filenames
> > contain quotes (wrong though they may be), while the remaining large
> > number of filenames have not quoting at all.

>
> > Is there a way to generate the required quoting? I realize I can
> > prepend backslashes to all nonstandard characters, but simply quoting
> > the whole thing seemed alot simpler than identifying all nonstandard
> > characters -- if it can be made to work.

>
> > Why do the above 3 "find" commands generate such strange quoting?

>
> > Thanks!

>
> The `` generates a list of IFS-separated tokens.
> It is safer to read the file line by line,
> and each time run a find command:
>
> while read -r line
> do
> find "$line" ...
> done < List.txt


Thanks, Michael. It works like a charm. I also learned that you can
pipe into a loop using "<" at the end, or using "|" at the start.

I looked up bash's "read", but I'm confused by the delimiting. It
says the IFS variable (which I assume is the default, since I didn't
change it) delimits the words in the line. The -r switch simply says
that backslashing isn't used -- not sure where that fits in, since I
don't have such a character in List.txt. It does not say that IFS is
ignored -- yet this must be what is happening, since the entire
contents of the physical line is stuffed into $line (else the find
command would report and error). So why is -r needed, and why is IFS
*apparently* not used here?

Thanks!

  Réponse avec citation
Vieux 25/07/2007, 23h57   #4
Mister.Fred.Ma@gmail.com
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Bash: Strange quoting in pipelined commands

On Jul 25, 6:14 pm, Michael Tosch <eed...@NO.eed.SPAM.ericsson.PLS.se>
wrote:
> Mister.Fred...@gmail.com wrote:
> > I have the following files/subdirectories listed in List.txt.

>
> > $cat List.txt

>
> > FixDiff.out
> > Temp.txt
> > diff.out
> > dog &cat

>
> > There are no leading or trailing spaces on each line. I want to
> > submit this to "find" after quoting each line. This command seems to
> > do the quoting:

>
> > cat List.txt | sed -e 's/.*/"&"/'

>
> > It generates:

>
> > "FixDiff.out"
> > "Temp.txt"
> > "diff.out"
> > "dog &cat"

>
> > Here is how I fed it to the "find" command. The head command simply
> > ensures that I don't pollute the display with "find" output, and that
> > no time is wasted on the find command, thus enabling me to quickly see
> > the expanded command from "set -x".

>
> > set -x
> > find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0
> > find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0
> > find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0

>
> > Here is the output:

>
> > $ find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0

>
> > find '"' 'FixDiff.out"' '"' 'Temp.txt"' '"' 'diff.out"' '"' dog
> > '&cat"' -type f

>
> > $ find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0

>
> > find FixDiff.out Temp.txt diff.out dog '&cat' -type f

>
> > $ find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0

>
> > find ''\''' 'FixDiff.out'\''' ''\''' 'Temp.txt'\''' ''\'''
> > 'diff.out'\''' ''\''' dog '&cat'\''' -type f

>
> > The 1st "find" is what I expected to work, but it generates extra
> > single-quotes. The 2nd "find" is a debugging step to find out exactly
> > what happens when the 4-line output of "cat | sed" is put onto a
> > single physical line for "find". Apparently, spaces are not
> > protected, though ampersands are. Leading quotes are protected, but
> > are considered separated out as distinct arguments.

>
> > The above is just a illustration of this behaviour. The actual usage
> > involves grepping a file instead of cat'ing it. The result is even
> > stranger -- using the 1st "find" above, only the 1st 2 filenames
> > contain quotes (wrong though they may be), while the remaining large
> > number of filenames have not quoting at all.

>
> > Is there a way to generate the required quoting? I realize I can
> > prepend backslashes to all nonstandard characters, but simply quoting
> > the whole thing seemed alot simpler than identifying all nonstandard
> > characters -- if it can be made to work.

>
> > Why do the above 3 "find" commands generate such strange quoting?

>
> > Thanks!

>
> The `` generates a list of IFS-separated tokens.
> It is safer to read the file line by line,
> and each time run a find command:
>
> while read -r line
> do
> find "$line" ...
> done < List.txt


Thanks, Michael. It works like a charm. I also learned that you can
pipe into a loop using "<" at the end, or using "|" at the start.

I looked up bash's "read", but I'm confused by the delimiting. It
says the IFS variable (which I assume is the default, since I didn't
change it) delimits the words in the line. The -r switch simply says
that backslashing isn't used -- not sure where that fits in, since I
don't have such a character in List.txt. It does not say that IFS is
ignored -- yet this must be what is happening, since the entire
contents of the physical line is stuffed into $line (else the find
command would report and error). So why is -r needed, and why is IFS
*apparently* not used here?

Thanks!

  Réponse avec citation
Vieux 26/07/2007, 00h24   #5
Michael Tosch
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Bash: Strange quoting in pipelined commands

Mister.Fred.Ma@gmail.com wrote:
> On Jul 25, 6:14 pm, Michael Tosch <eed...@NO.eed.SPAM.ericsson.PLS.se>
> wrote:
>> Mister.Fred...@gmail.com wrote:
>>> I have the following files/subdirectories listed in List.txt.
>>> $cat List.txt
>>> FixDiff.out
>>> Temp.txt
>>> diff.out
>>> dog &cat
>>> There are no leading or trailing spaces on each line. I want to
>>> submit this to "find" after quoting each line. This command seems to
>>> do the quoting:
>>> cat List.txt | sed -e 's/.*/"&"/'
>>> It generates:
>>> "FixDiff.out"
>>> "Temp.txt"
>>> "diff.out"
>>> "dog &cat"
>>> Here is how I fed it to the "find" command. The head command simply
>>> ensures that I don't pollute the display with "find" output, and that
>>> no time is wasted on the find command, thus enabling me to quickly see
>>> the expanded command from "set -x".
>>> set -x
>>> find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0
>>> find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0
>>> find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0
>>> Here is the output:
>>> $ find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0
>>> find '"' 'FixDiff.out"' '"' 'Temp.txt"' '"' 'diff.out"' '"' dog
>>> '&cat"' -type f
>>> $ find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0
>>> find FixDiff.out Temp.txt diff.out dog '&cat' -type f
>>> $ find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0
>>> find ''\''' 'FixDiff.out'\''' ''\''' 'Temp.txt'\''' ''\'''
>>> 'diff.out'\''' ''\''' dog '&cat'\''' -type f
>>> The 1st "find" is what I expected to work, but it generates extra
>>> single-quotes. The 2nd "find" is a debugging step to find out exactly
>>> what happens when the 4-line output of "cat | sed" is put onto a
>>> single physical line for "find". Apparently, spaces are not
>>> protected, though ampersands are. Leading quotes are protected, but
>>> are considered separated out as distinct arguments.
>>> The above is just a illustration of this behaviour. The actual usage
>>> involves grepping a file instead of cat'ing it. The result is even
>>> stranger -- using the 1st "find" above, only the 1st 2 filenames
>>> contain quotes (wrong though they may be), while the remaining large
>>> number of filenames have not quoting at all.
>>> Is there a way to generate the required quoting? I realize I can
>>> prepend backslashes to all nonstandard characters, but simply quoting
>>> the whole thing seemed alot simpler than identifying all nonstandard
>>> characters -- if it can be made to work.
>>> Why do the above 3 "find" commands generate such strange quoting?
>>> Thanks!

>> The `` generates a list of IFS-separated tokens.
>> It is safer to read the file line by line,
>> and each time run a find command:
>>
>> while read -r line
>> do
>> find "$line" ...
>> done < List.txt

>
> Thanks, Michael. It works like a charm. I also learned that you can
> pipe into a loop using "<" at the end, or using "|" at the start.
>
> I looked up bash's "read", but I'm confused by the delimiting. It
> says the IFS variable (which I assume is the default, since I didn't
> change it) delimits the words in the line. The -r switch simply says
> that backslashing isn't used -- not sure where that fits in, since I
> don't have such a character in List.txt. It does not say that IFS is
> ignored -- yet this must be what is happening, since the entire
> contents of the physical line is stuffed into $line (else the find
> command would report and error). So why is -r needed, and why is IFS
> *apparently* not used here?
>


In case List.txt has

line\
1

a normal read would compose that to "line1", therefore the -r

IFS is used to split the line:

while read -r word1 word2 rest

But we read the entire line.


--
Michael Tosch @ hp : com
  Réponse avec citation
Vieux 26/07/2007, 01h55   #6
Mister.Fred.Ma@gmail.com
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Bash: Strange quoting in pipelined commands

On Jul 25, 7:24 pm, Michael Tosch <eed...@NO.eed.SPAM.ericsson.PLS.se>
wrote:
> Mister.Fred...@gmail.com wrote:
> > On Jul 25, 6:14 pm, Michael Tosch <eed...@NO.eed.SPAM.ericsson.PLS.se>
> > wrote:
> >> Mister.Fred...@gmail.com wrote:
> >>> I have the following files/subdirectories listed in List.txt.
> >>> $cat List.txt
> >>> FixDiff.out
> >>> Temp.txt
> >>> diff.out
> >>> dog &cat
> >>> There are no leading or trailing spaces on each line. I want to
> >>> submit this to "find" after quoting each line. This command seems to
> >>> do the quoting:
> >>> cat List.txt | sed -e 's/.*/"&"/'
> >>> It generates:
> >>> "FixDiff.out"
> >>> "Temp.txt"
> >>> "diff.out"
> >>> "dog &cat"
> >>> Here is how I fed it to the "find" command. The head command simply
> >>> ensures that I don't pollute the display with "find" output, and that
> >>> no time is wasted on the find command, thus enabling me to quickly see
> >>> the expanded command from "set -x".
> >>> set -x
> >>> find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0
> >>> find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0
> >>> find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0
> >>> Here is the output:
> >>> $ find ` cat List.txt | sed -e 's/.*/"&"/' ` -type f 2>&1 | head -n 0
> >>> find '"' 'FixDiff.out"' '"' 'Temp.txt"' '"' 'diff.out"' '"' dog
> >>> '&cat"' -type f
> >>> $ find ` cat List.txt | sed -e 's/.*/&/' ` -type f 2>&1 | head -n 0
> >>> find FixDiff.out Temp.txt diff.out dog '&cat' -type f
> >>> $ find ` cat List.txt | sed -e "s/.*/'&'/" ` -type f 2>&1 | head -n 0
> >>> find ''\''' 'FixDiff.out'\''' ''\''' 'Temp.txt'\''' ''\'''
> >>> 'diff.out'\''' ''\''' dog '&cat'\''' -type f
> >>> The 1st "find" is what I expected to work, but it generates extra
> >>> single-quotes. The 2nd "find" is a debugging step to find out exactly
> >>> what happens when the 4-line output of "cat | sed" is put onto a
> >>> single physical line for "find". Apparently, spaces are not
> >>> protected, though ampersands are. Leading quotes are protected, but
> >>> are considered separated out as distinct arguments.
> >>> The above is just a illustration of this behaviour. The actual usage
> >>> involves grepping a file instead of cat'ing it. The result is even
> >>> stranger -- using the 1st "find" above, only the 1st 2 filenames
> >>> contain quotes (wrong though they may be), while the remaining large
> >>> number of filenames have not quoting at all.
> >>> Is there a way to generate the required quoting? I realize I can
> >>> prepend backslashes to all nonstandard characters, but simply quoting
> >>> the whole thing seemed alot simpler than identifying all nonstandard
> >>> characters -- if it can be made to work.
> >>> Why do the above 3 "find" commands generate such strange quoting?
> >>> Thanks!
> >> The `` generates a list of IFS-separated tokens.
> >> It is safer to read the file line by line,
> >> and each time run a find command:

>
> >> while read -r line
> >> do
> >> find "$line" ...
> >> done < List.txt

>
> > Thanks, Michael. It works like a charm. I also learned that you can
> > pipe into a loop using "<" at the end, or using "|" at the start.

>
> > I looked up bash's "read", but I'm confused by the delimiting. It
> > says the IFS variable (which I assume is the default, since I didn't
> > change it) delimits the words in the line. The -r switch simply says
> > that backslashing isn't used -- not sure where that fits in, since I
> > don't have such a character in List.txt. It does not say that IFS is
> > ignored -- yet this must be what is happening, since the entire
> > contents of the physical line is stuffed into $line (else the find
> > command would report and error). So why is -r needed, and why is IFS
> > *apparently* not used here?

>
> In case List.txt has
>
> line\
> 1
>
> a normal read would compose that to "line1", therefore the -r
>
> IFS is used to split the line:
>
> while read -r word1 word2 rest
>
> But we read the entire line.


Thanks, Michael.

Fred

  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 12h38.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,28655 seconds with 14 queries