OVH Cloud OVH Cloud

backslash :: protection chaine pour commande externe

11 réponses
Avatar
Eric Deveaud
Bonjour,

je sèche sur un problème que je pensait simple.

comment traiter des chaines de caratères pour protéger certains
caractéres avant de les passer au shell

j'utilise Popen avec shell=True (et j'ai besoin de shell=True)
pour récupérer des résultats de comandes externes

il se trouve qu'un cas d'utilisation me pose soucis.
les noms de fichiers à passer à mes commande comportent des
caractères qu'il me faut protéger (espace, parenthèses,
accolades et autre caractères particuliers pour le shell)

naïvement j'ai fait une boucle pour remplacer tout caractère non
alphanumérique par backslash suivi de ce caractère.

def protect_file(mmfile):
new = []
char_accepted = string.ascii_letters + string.digits +
os.path.sep
escape = '\\'
for c in mmfile:
if c in char_accepted:
new.append(c)
else:
new.append(escape + c)
return ''.join(new)

le hic, c'est que du coup j'introduit 2 backslah dans ma chaine,
celle ci etant passée telle qu'elle au shell. bien évidement
l'effet n'est pas du tout celui voulu ;-(

une idée de comment m'en sortir ?

Eric

10 réponses

1 2
Avatar
Alain Ketterlin
Eric Deveaud writes:

comment traiter des chaines de caratères pour protéger certains
caractéres avant de les passer au shell

j'utilise Popen avec shell=True (et j'ai besoin de shell=True)
pour récupérer des résultats de comandes externes



Ca aiderait de savoir quel est le shell en question. Je suppose que
c'est un shell POSIX.

Si tu entoures ta chaîne de quotes simples (d'apostrophes), il ne te
reste plus qu'à protéger les... quotes simples. Quelque chose com me :

def p(s):
return '''"'"'''.join(["'"+t+"'" for t in s.split("'")])

(pas testé).

-- Alain.
Avatar
Alain BARTHE
Eric Deveaud a écrit :
Bonjour,

je sèche sur un problème que je pensait simple.

comment traiter des chaines de caratères pour protéger certains
caractéres avant de les passer au shell

j'utilise Popen avec shell=True (et j'ai besoin de shell=True)
pour récupérer des résultats de comandes externes

il se trouve qu'un cas d'utilisation me pose soucis.
les noms de fichiers à passer à mes commande comportent des
caractères qu'il me faut protéger (espace, parenthèses,
accolades et autre caractères particuliers pour le shell)

naïvement j'ai fait une boucle pour remplacer tout caractère non
alphanumérique par backslash suivi de ce caractère.

def protect_file(mmfile):
new = []
char_accepted = string.ascii_letters + string.digits +
os.path.sep
escape = ''
for c in mmfile:
if c in char_accepted:
new.append(c)
else:
new.append(escape + c)
return ''.join(new)

le hic, c'est que du coup j'introduit 2 backslah dans ma chaine,
celle ci etant passée telle qu'elle au shell. bien évidement
l'effet n'est pas du tout celui voulu ;-(

une idée de comment m'en sortir ?

Eric



A tout hasard :

escape = ''
Avatar
Alain BARTHE
Alain BARTHE a écrit :
Eric Deveaud a écrit :
Bonjour,

je sèche sur un problème que je pensait simple.

comment traiter des chaines de caratères pour protéger certains
caractéres avant de les passer au shell
j'utilise Popen avec shell=True (et j'ai besoin de shell=True)
pour récupérer des résultats de comandes externes

il se trouve qu'un cas d'utilisation me pose soucis.
les noms de fichiers à passer à mes commande comportent des
caractères qu'il me faut protéger (espace, parenthèses,
accolades et autre caractères particuliers pour le shell)

naïvement j'ai fait une boucle pour remplacer tout caractère non
alphanumérique par backslash suivi de ce caractère.

def protect_file(mmfile):
new = []
char_accepted = string.ascii_letters + string.digits +
os.path.sep
escape = ''
for c in mmfile:
if c in char_accepted:
new.append(c)
else:
new.append(escape + c)
return ''.join(new)

le hic, c'est que du coup j'introduit 2 backslah dans ma chaine,
celle ci etant passée telle qu'elle au shell. bien évidement
l'effet n'est pas du tout celui voulu ;-(

une idée de comment m'en sortir ?

Eric



A tout hasard :

escape = ''



J'ai testé :


from subprocess import Popen

p = Popen ("ls -l mon fichier", shell = True)

Ca fonctionne : il suffit donc bien d'insérer *un* devant tes
caractères spéciaux.
Avatar
Alain BARTHE
Eric Deveaud a écrit :
Alain BARTHE wrote:
Eric Deveaud a écrit :

escape = ''



le hasard ne nous réussi pas

Python 2.6.1 (r261:67515, Jul 7 2009, 23:51:51)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more
information.
escape = ''






File "<stdin>", line 1
escape = ''
^
SyntaxError: EOL while scanning string literal





Désolé, j'avais pas vu le problème...
Avatar
Alain BARTHE
Eric Deveaud a écrit :
Alain BARTHE wrote:
Eric Deveaud a écrit :

escape = ''



le hasard ne nous réussi pas

Python 2.6.1 (r261:67515, Jul 7 2009, 23:51:51)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more
information.
escape = ''






File "<stdin>", line 1
escape = ''
^
SyntaxError: EOL while scanning string literal





J'ai testé aussi :

commande = "ls -l mon" + '' + " fichier"

print commande

p = Popen (commande, shell = True)

ca fonctionne et affiche :

ls -l mon fichier
-rw-r--r-- 1 barthe barthe 0 nov 17 16:59 mon fichier

le est interprété comme un seul caractère dans le print ainsi que
dans le Popen et la commande fonctionne.

J'ai pas testé avec les autres caractères spéciaux, mais ca devrait
fonctionner de même.

Sur quelle commande as tu testé ta première version ?
Avatar
Alain Ketterlin
Alain BARTHE writes:

p = Popen ("ls -l mon fichier", shell = True)

Ca fonctionne : il suffit donc bien d'insérer *un* devant tes
caractères spéciaux.



Attention : le backslash disparait seulement si il précède un car actère
spécial *pour Python*, dans les autres cas il reste en place (ce qui se
passe dans l'exemple ci-dessus). Voir
http://docs.python.org/reference/lexical_analysis.html#literals
Par exemple "un deux" et "un deux" ont la même valeur.

-- Alain.
Avatar
Eric Deveaud
Alain BARTHE wrote:
Eric Deveaud a écrit :

escape = ''



le hasard ne nous réussi pas

Python 2.6.1 (r261:67515, Jul 7 2009, 23:51:51)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more
information.
escape = ''






File "<stdin>", line 1
escape = ''
^
SyntaxError: EOL while scanning string literal







Avatar
Eric Deveaud
Alain Ketterlin wrote:
Eric Deveaud writes:

> comment traiter des chaines de caratères pour protéger certains
> caractéres avant de les passer au shell
>
> j'utilise Popen avec shell=True (et j'ai besoin de shell=True)
> pour récupérer des résultats de comandes externes

Ca aiderait de savoir quel est le shell en question. Je suppose que
c'est un shell POSIX.



POSIX en effet, le shell en question est sh

Si tu entoures ta chaîne de quotes simples (d'apostrophes), il ne te
reste plus qu'à protéger les... quotes simples. Quelque chose comme :

def p(s):
return '''"'"'''.join(["'"+t+"'" for t in s.split("'")])



les quotes bloquent bien l'expension de caratères "spéciaux" en
effet, j'avoue être resté bloqué sur le backslah.

c'est une solution que je vais tester ça de ce pas.

Eric
Avatar
Eric Deveaud
Alain BARTHE wrote:

from subprocess import Popen

p = Popen ("ls -l mon fichier", shell = True)

Ca fonctionne : il suffit donc bien d'insérer *un* devant tes
caractères spéciaux.



là est le truc comment insérer *un et un seul* backslah devant
certains caratères ?

Eric
Avatar
Philippe Bouige
Le 17-11-2009, Eric Deveaud a écrit :
Bonjour,

je sèche sur un problème que je pensait simple.



J'ai trouvé cette solution, mais je n'ai pas mieux :-)

>>> from subprocess import Popen
>>>
>>> escape = " "[0]
>>>
>>> Popen( "ls -la", shell=True)

-rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:01 (
-rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:09 (
-rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:00 ()

>>> comd1 = escape + '(' + escape + ' ' + escape

>>> Popen(comd1, shell=True)
<subprocess.Popen object at 0x8224e0c>
>>> -rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:01 (


>>> comd2 = 'ls -la ' + escape + '(' + escape + ' ' + escape + escape +
escape
>>> Popen(comd2, shell=True)
<subprocess.Popen object at 0x822858c>
>>> -rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:09 (

autre exemple :

touch '( &'
-rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:22 ( &

sous python :

>>> from subprocess import Popen
>>>
>>> escape = ' '[0]
>>>
>>> cmd3 = 'ls -la ' + escape + '(' + escape + ' ' + escape + '&'
>>> Popen(cmd3, shell=True)
<subprocess.Popen object at 0x8224eac>
>>> -rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:22 ( &
1 2