CommandLine префикс-макро - запустить команду в Bash

Столкнулись с проблемой в использовании Far? Здесь можно получить помощь.
Post Reply
EGez
Posts: 144
Joined: Thu 04 Oct, 2012 13:53
Location: Hamburg, DE
Has thanked: 2 times
Been thanked: 2 times

CommandLine префикс-макро - запустить команду в Bash

Post by EGez » Fri 26 Oct, 2018 23:28

Доброй ночи.

Вопрос к гуру у меня.

По работе и дома приходится очень часто пользоваться другими командными интерпретерами вроде Bash.

Для того, чтобы запускать некоторые команды напрямую из Far, пытаюсь для этого использовать CommandLine макро:

Code: Select all

CommandLine {
	prefixes = 'bash'; action = function(prefix, cmd)
		panel.GetUserScreen()
		pcall(function()
			os.execute(("bash -xc %q"):format(cmd))
		end)
		panel.SetUserScreen()
	end;
}
Вроде бы работает, но только если команда полностью состоит из (в моем случае) АСКИИ знаков.

Code: Select all

bash:find directory 
+ find directory
directory
directory/file
directory/файл
Если же команда вдруг содержит национальные знаки вроде кириллицы или немецких умляутов, то получается вот такой вот бред:

Code: Select all

bash:find папка 
+ 'find папка'
bash: find папка: command not found
Обратите внимание и на кавычки в команде. Пробовал выдавать результат вызова :format() перед выполнением, разницы не вижу никакой, все показывается нормально.

Что-то квотит команду полностью и кодировка не совпала похоже.

Несколько месяцев уже думаю над этим, ничего в голову не приходит...

Что я делаю не так? Как научить его?

Windows 7, Far 3.0.5279, Bash 4.4.19 из MSYS2.

Спасибо

Yegor
Posts: 938
Joined: Mon 04 Apr, 2005 13:41
Location: San Ramon, CA / Kharkov, UA
Has thanked: 3 times
Been thanked: 11 times

CommandLine префикс-макро - запустить команду в Bash

Post by Yegor » Fri 26 Oct, 2018 23:55

search.php?keywords=os.execute+utf

Первая ссылка.

EDIT: даже без ссылок, в результатах поиска есть ответ.
Last edited by Yegor on Sat 27 Oct, 2018 00:05, edited 1 time in total.
Мы не можем ждать милостей от Фара, взять их у него — наша задача! (C) Мичурин

buniak_a_h
Posts: 582
Joined: Sat 20 Apr, 2013 00:17
Location: Питер
Has thanked: 57 times
Been thanked: 13 times
Contact:

CommandLine префикс-макро - запустить команду в Bash

Post by buniak_a_h » Sat 27 Oct, 2018 02:32

1.
2. Простой способ - перекодировать командную строку, передаваемую интерпретатору, в ANSI:

Code: Select all

local function UTF_8ToANSI(str)
  return win.WideCharToMultiByte(win.MultiByteToWideChar(str, 65001), win.GetACP())
end
os.execute(win.Utf8ToOem('cmd /C echo проба'))
Проверено на cmd, но не думаю, что будет разница с Bash
Last edited by buniak_a_h on Sat 27 Oct, 2018 02:32, edited 1 time in total.

Shmuel
Posts: 5574
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 21 times
Been thanked: 186 times

CommandLine префикс-макро - запустить команду в Bash

Post by Shmuel » Sat 27 Oct, 2018 08:15

EGez, попробуйте в вашей функции action заменить os.execute на win.system. Возможно, что этого будет достаточно.

EGez
Posts: 144
Joined: Thu 04 Oct, 2012 13:53
Location: Hamburg, DE
Has thanked: 2 times
Been thanked: 2 times

CommandLine префикс-макро - запустить команду в Bash

Post by EGez » Tue 30 Oct, 2018 22:49

Yegor wrote:
Fri 26 Oct, 2018 23:55
Первая ссылка.
Да, Егор, спасибо за ответ, но:
У меня ANSI - это 1252, а OEM - 850, в них нет аналогов кириллице.
И соответственно:
И если в пути присутствует что-то, не имеющее соответствия в ANSI, то будет ошибка.

EGez
Posts: 144
Joined: Thu 04 Oct, 2012 13:53
Location: Hamburg, DE
Has thanked: 2 times
Been thanked: 2 times

CommandLine префикс-макро - запустить команду в Bash

Post by EGez » Tue 30 Oct, 2018 23:06

Shmuel wrote:
Sat 27 Oct, 2018 08:15
EGez, попробуйте в вашей функции action заменить os.execute на win.system. Возможно, что этого будет достаточно.
Тут уже движение какое-то:

Code: Select all

bash:find папка
+ 'find папка'
bash: find папка: command not found
Кодировка похоже прошла нормально. И квотится вроде как bash -xc "find папка", но потом обрамляет всю команду в кавычки и, похоже, пытается это как единую команду выполнить, включая аргумент.

Для сравнения (без кавычек):

Code: Select all

bash:find directory
+ find directory
directory
directory/file
directory/файл
Не понимаю.

EGez
Posts: 144
Joined: Thu 04 Oct, 2012 13:53
Location: Hamburg, DE
Has thanked: 2 times
Been thanked: 2 times

CommandLine префикс-макро - запустить команду в Bash

Post by EGez » Tue 30 Oct, 2018 23:11

Ага, попробовал напрямую:

Code: Select all

... >bash -xc "find папка"
+ 'find папка'
/usr/bin/bash: find папка: command not found

... >bash -xc "find directory"
+ find directory
directory
directory/file
directory/файл
Походу Баш ее сам квотит.

User avatar
DrKnS
Posts: 5004
Joined: Thu 04 Aug, 2005 06:44
Location: Kyiv
Has thanked: 4 times
Been thanked: 166 times

CommandLine префикс-макро - запустить команду в Bash

Post by DrKnS » Tue 30 Oct, 2018 23:24

Code: Select all

D:\dev\far_git\FarManager\far>bash --version
GNU bash, version 4.3.42(5)-release (x86_64-pc-msys)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

D:\dev\far_git\FarManager\far>bash -xc "find папка"
+ find папка
find: '\320\277\320\260\320\277\320\272\320\260': No such file or directory

Yegor
Posts: 938
Joined: Mon 04 Apr, 2005 13:41
Location: San Ramon, CA / Kharkov, UA
Has thanked: 3 times
Been thanked: 11 times

CommandLine префикс-макро - запустить команду в Bash

Post by Yegor » Tue 30 Oct, 2018 23:29

Я давно себе сделал тупой макрос и забыл:

Code: Select all

Macro {
  area = "Shell";
  key = "CtrlShiftEnter";
  description = "Execute bash command";
  
  action = function()
	local cmdLine = panel.GetCmdLine()
	Keys("Esc")
	print("bash -c \"" .. cmdLine .. "\"")
	Keys("Enter")
  end;
}

Code: Select all

C:\Far\Profile\Macros\scripts>bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

C:\Far\Profile\Macros\scripts>bash -c "find папка"
папка
Last edited by Yegor on Tue 30 Oct, 2018 23:31, edited 1 time in total.
Мы не можем ждать милостей от Фара, взять их у него — наша задача! (C) Мичурин

EGez
Posts: 144
Joined: Thu 04 Oct, 2012 13:53
Location: Hamburg, DE
Has thanked: 2 times
Been thanked: 2 times

CommandLine префикс-макро - запустить команду в Bash

Post by EGez » Wed 31 Oct, 2018 00:09

Yegor wrote:
Tue 30 Oct, 2018 23:29
Я давно себе сделал тупой макрос и забыл
[...]
Егор, я давно пытаюсь намекнуть, что у меня "винда" не русская. У меня нет кириллических знаков в стандартных кодировках. А поменять я ее по некоторым причинам не могу.

И да:

Code: Select all

... >bash --version
GNU bash, version 4.4.19(3)-release (i686-pc-msys)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Похоже это не совсем тривиально...

EGez
Posts: 144
Joined: Thu 04 Oct, 2012 13:53
Location: Hamburg, DE
Has thanked: 2 times
Been thanked: 2 times

CommandLine префикс-макро - запустить команду в Bash

Post by EGez » Mon 05 Nov, 2018 21:43

Добрый вечер.

Кажется я нашел:
Проблема была в том, что однажды я установил переменную LC_ALL=C.UTF-8, что переписывало все и привело к тому, что Баш не совсем правильно рассматривал non-ASCII символы.

Дабы не спровоцировать больших изменений, попробовал просто указать LC_CTYPE=en_US.UTF-8, а остальное оставил C.UTF-8.

И получилось:

Code: Select all

CommandLine {
	prefixes = 'bash'; description = 'Execute with bash'; action = function(prefix, cmd)
		panel.GetUserScreen()
		pcall(function()
			win.system(('bash -xc %q'):format(cmd))
		end)
		panel.SetUserScreen()
	end;
}

Code: Select all

bash:find "с пробелом"
+ find 'с пробелом'
с пробелом
с пробелом/file
с пробелом/файл
Суть проблемы описана так:
The C locale is a special locale that is meant to be the simplest locale. You could also say that while the other locales are for humans, the C locale is for computers. In the C locale, characters are single bytes, the charset is ASCII (well, is not required to, but in practice will be in the systems most of us will ever get to use), the sorting order is based on the byte values, the language is usually US English (though for application messages (as opposed to things like month or day names or messages by system libraries), it's at the discretion of the application author) and things like currency symbols are not defined.
Всем спасибо.
Last edited by EGez on Mon 05 Nov, 2018 22:53, edited 2 times in total.

Post Reply

Return to “Нужна помощь”