Итак, я понял, что работаю в обратном направлении, и это сработало для меня
sudo find . -type f \( -name '*.squashfs' -o -name "*.SQFS" \) -exec cp {} /tmp/fs.squashfs \; && sudo unsquashfs /tmp/fs.squashfs
Что я в итоге получил благодаря помощи пользователей! (Мне нужна была возможность поиска по разным параметрам и возможность добавить больше в будущем)
find /tmp/mnt \( -iname '*.squashfs' -o -iname "*.SQFS" \) -exec unsquashfs -d /tmp/squashfs-root/ {} \;
Команда apropos
полезна во многих отношениях, но она также дает вам много «мусора». Большинство вещей, которые вы перечисляете, являются подпрограммами библиотеки C (, для этого предназначен раздел 3 руководства ), которые вы не можете использовать непосредственно из оболочки.
Чтобы их использовать, вам нужно написать программу на C, которая их вызывает. Это выходит за рамки тем, охватываемых этим конкретным сайтом (, это будет тема на StackOverflow).
Вот, таким образом, ответы на ваши вопросы:
Я знаю, что вы это знаете, но для полноты картины :В оболочке, если у вас есть строка в переменной string
, вы можете сделать
string='hello world'
printf 'Length of string "%s" is %d\n' "$string" "${#string}"
Это напечатает Length of string "hello world" is 11
в терминале, где 11
исходит из ${#string}
, которое расширяется до длины строки в $string
.
Внутри оболочка вполне может использовать один из библиотечных вызовов, которые вы перечислили, для вычисления длины.
Это наиболее эффективный способ получить длину строки, хранящейся в переменной оболочки, в самой оболочке.
Также обратите внимание, что ${#string}
— это расширение параметра оболочки POSIX , поэтому оно переносимо между всеми оболочками, которые заявляют о любой степени соответствия POSIX.
Возможно, вам не следует этого делать, но вы можете. Ответ Кусалананды лучше подходит для поставленной задачи и объясняет проблему.Поскольку вы спросили конкретно, как использовать любые библиотечные вызовы внутри терминала, вот несколько способов...
Tiny C Compiler(tcc
)поддерживает -run
флаг , который позволяет вам (фактически )интерпретировать код C путем написания небольшой программы, поэтому вы можете использовать любые библиотечные вызовы внутри терминала посредством одного вызова этого.
Вы можете запустить функцию strnlen
следующим образом:
$ tcc -run <(echo '#include <stdio.h>'; echo '#include <string.h>'; echo 'void main(int argc, char **argv) {printf("%i\n", strnlen(argv[1], 1024));}') "Hello world"
11
При этом используется подстановка процесса из Bash, zsh и других оболочек для предоставления tcc
файла для чтения, который, по-видимому, содержит результаты всех echo
s; есть другие варианты.
Вы можете создать функцию, которая будет генерировать это для вас:
call_library_function_s_i() {
func=$1
shift
tcc -run <(echo '#include <stdio.h>'; echo '#include <string.h>'; echo 'void main(int argc, char **argv) {printf("%i\n", '$func'(argv[1]));}') "$*"
}
$ call_library_function_s_i strlen hello world
(Я использовал strlen
здесь, так что это строка унарной функции ->int -вам понадобится отдельная функция для каждой другой арности и типа возвращаемого значения ).
Другим вариантом является подключаемый модуль ctypes.sh
Bash Тэвиса Орманди, который объединяет dlopen
и dlsym
. Это, вероятно, самое близкое приближение к тому, что вы пытались. Вы можете использовать, например,:
$ dlcall -r uint64 strlen "hello world"
и вызовет функцию, как и ожидалось.
Это самый прямой способ сделать это "из терминала", но вряд ли это будет что-то из вашего дистрибутива, поэтому вам придется устанавливать его вручную (, что нетривиально ). Вот несколько информативных цитат с собственного веб-сайта ctypes.sh
, чтобы дать общее представление о том, как люди относятся к этому:
- "that's disgusting"
- "this has got to stop"
- "you've gone too far with this"
Для других оболочек могут быть подобные инструменты, но я о них не знаю. Теоретически нет никаких причин, по которым не может быть отдельной команды, которая делала бы это именно для простых случаев, но я несколько удивлен, что не смог найти ее...
... так что я сделал один!dlcall
позволяет вызывать библиотечные функции из командной строки:
$ dlcall strnlen "hello world" 6
$ dlcall sin 2.5
$ dlcall strchr "hello world" -c ' '
Он поддерживает ограниченный набор прототипов функций, в настоящее время он не очень надежен или отказоустойчив, но теперь он существует.
Вы также можете использовать, например, Python и python -c 'import ctypes; import sys; print(ctypes.cdll.LoadLibrary("libc.so.6").strlen(" ".join(sys.argv[1:])))' hello world
, но это, безусловно, не самый простой способ. Perl, Ruby и другие языки имеют схожие функции, которые вы могли бы использовать.
Итак, ответы на ваши вопросы:
В общем, вам почти наверняка будет лучше сделать это любым другим способом.
Я бы не стал делать это только для strlen()
, но иногда это полезный прием для проверки кода C.
user@host:~$ gdb gdb (gdb) start Temporary breakpoint 1,... in main () (gdb) print strlen("foobar") $1 = 6
Здесь gdb
— отладчик GNU, и обычно для отладки после него требуется имя программы. Поскольку у нас его нет, этот пример дает его для отладки. Затем start
запускает программу, после чего gdb
можно использовать для выполнения произвольного кода на C.