#file #arguments #exec #tcl
#файл #аргументы #exec #tcl
Вопрос:
Я работаю над проводником файлов inTCL / Tk и хочу добавить небольшую деталь для выполнения команд с текущим выбором (используя %l %f). %l выполняется с полным списком, а %f выполняет команду commmand с каждым файлом. моя единственная проблема в том, что если я ввожу команду типа «gedit», например, это работает, но как только я ввожу команду с аргументом, она не работает… Я искал везде, и я этого не понимаю… Если бы кто-нибудь мог мне помочь … кстати, getl var Name — это функция, которая возвращает мне имя файла с полным путем (/home / …), и если я возвращаю строку, которая должна быть выполнена, и помещаю ее в терминал, она работает…
Вот код:
proc tl_exec {liste command } {
#lorsqu'il faut effectué la commande avec la liste en param
if { [string first "%l" $command] > 0} {
foreach v $liste {
lappend args [getl $v Name]
}
set com [string map [list "%l" [join $args " "] ] $command ]
puts $com
set val [exec [split $com " "] ]
} elseif { [string first "%f" $command] > 0} {
#lorsqu'il faut effectué la commande pour chaque fichier
foreach v $liste {
set com [string map list ["%f" [getl $v "Name"] ] $command ]
lappend val [ exec [split $com " "] ]
}
} else {
#lorsqu'on a pas de fichiers
set val [exec $command]
}
}
Большое спасибо
Комментарии:
1. Ho да, кстати, ошибка, которая возвращается для чего угодно, — «не удалось выполнить такой файл или каталог …» Я предполагаю, что это как-то связано с отсутствием магических кавычек и тем фактом, что он рассматривает все как единую команду…
2. Ну, допустим, я глуп и не могу открыть глаза 🙂 Только что выяснил: я должен использовать eval exec, чтобы иметь эту вещь… Извините за вопрос с автоматическим ответом… Кстати, нашел полезную ссылку «распространенные ошибки в TCL / TK»: phaseit.net/claird/comp.lang.tcl/fmm.html
Ответ №1:
В вашем коде больше одной проблемы, вероятно, он также будет прерываться из-за специальных символов или пробелов в именах файлов, поскольку вы вообще не используете кавычки.
Но вы правы в том, что exec рассматривает все как единую команду.
set val [exec [split $com " "] ]
делает не то, что вы ожидаете, split возвращает список, но автоматически не превращает этот список в дополнительные аргументы для exec.
Если вы используете Tcl 8.5, вы можете попробовать:
set val [exec {*}[split $com " "] ]
который превращает список в отдельные аргументы для передачи в exec.
Но используемый вами код в целом хрупкий, поскольку вы не обрабатываете никаких кодов выхода или программ, записываемых в stderr, поэтому для обеспечения надежности потребуется более сложное решение.
Взгляните на http://wiki.tcl.tk/1039 особенно обсуждения внизу страницы.
Комментарии:
1. ну да, но сначала я тестировал … спасибо за помощь, у меня старая версия Tcl, в которой нет {*} как я могу ее заменить?
2. Вы можете использовать set val [eval exec [split $ com » «] ] . Однако у этого есть немало проблем с безопасностью.
3. Это будет иметь те же проблемы с безопасностью, что и версия с
{*}
, посколькуsplit
гарантируется создание правильного списка.4. Я был неправ насчет дополнительных проблем безопасности, как указал Донал. Если бы вы не использовали разделенную конструкцию, как вы это делали, а передали строку напрямую, у нее были бы дополнительные проблемы с безопасностью из-за вычисления строки. Но поскольку split создает правильный список, оценка защищена от внедрения кода или других неприятностей.