Если я понимаю правильно, Вы хотите это:
find /path -mindepth 2 -type f -not -perm 0755
Или возможно просто это, если мое понимание прочь:
find /path/to -type f -not -perm 0755
Определите эти две функции (обычно доступный на других языках):
chr() {
[ "$1" -lt 256 ] || return 1
printf "\\$(printf '%03o' "$1")"
}
ord() {
LC_CTYPE=C printf '%d' "'$1"
}
Использование:
chr 65
A
ord A
65
Вы видите весь набор с:
$ man ascii
Вы вложите таблицы, восьмеричные, шестнадцатеричные, и десятичные.
Если Вы хотите расширить его до символов UTF-8 (предполагающий, что Вы находитесь в локали UTF-8):
$ perl -CA -le 'print ord shift'
128520
$ perl -CS -le 'print chr shift' 128520
С bash
, ksh
или zsh
builtins:
$ printf "\U$(printf %08x 128520)\n"
iceweasel
на Debian sid
. Шрифтом, как подтверждено веб-консолью iceweasel является "DejaVu Sans", и у меня есть ttf-dejavu ttf-dejavu-core ttf-dejavu-extra пакеты, установленные, которые прибывают из Debian с восходящим потоком в dejavu-fonts.org
– Stéphane Chazelas
02.10.2013, 12:10
ctbl()
кажется, правильно позволяет мне отобразить его и отрезать символ от верхней части строки с printf
, но это помещает 4*((o1=360)>=(d1=240)|(o2=237)>=(d2=159)|(o3=230)>=(d3=152)|(o4=210)>=(d4=136))
в $OPTARG
для значений байта.
– mikeserv
18.11.2015, 07:52
Это работает хорошо,
echo "A" | tr -d "\n" | od -An -t uC
echo "A" ### Emit a character.
| tr -d "\n" ### Remove the "newline" character.
| od -An -t uC ### Use od (octal dump) to print:
### -An means Address none
### -t select a type
### u type is unsigned decimal.
### C of size (one) char.
точно эквивалентный:
echo -n "A" | od -An -tuC ### Not all shells honor the '-n'.
echo -n
подавляет запаздывание новой строки, избавляющей от необходимости tr -d "\n"
– Gowtham
26.09.2013, 19:59
echo
, не в Unix совместимый echos, например. printf %s A
был бы портативный.
– Stéphane Chazelas
27.09.2013, 11:44
Я иду для простого (и изящный?) Решение для Bash:
for i in {a..z}; do echo $(printf "%s %d" "$i" "'$i"); done
Поскольку в сценарии можно использовать следующее:
CharValue="A"
AscValue=`printf "%d" "'$CharValue"
Заметьте одинарную кавычку перед CharValue. Это обязано...
printf "%d"
. огромное спасибо
– Bernhard
27.09.2013, 12:11
konsole
xxd<нажмите enter>
вы получите что-то вроде:
mariank@dd903c5n1 ~ $ xxd
û0000000: fb
вы знаете, что символ, который вы вставили, имеет шестнадцатеричный код 0xfb
Не сценарий оболочки, но работает
awk 'BEGIN{for( i=97; i<=122;i++) printf "%c %d\n",i,i }'
Образец вывода
xieerqi:$ awk 'BEGIN{for( i=97; i<=122;i++) printf "%c %d\n",i,i }' | head -n 5
a 97
b 98
c 99
d 100
e 101
ctbl() for O in 0 1 2 3
do for o in 0 1 2 3 4 5 6 7
do for _o in 7 6 5 4 3 2 1 0
do case $((_o=(_o+=O*100+o*10)?_o:200)) in
(*00|*77) set "${1:+ \"}\\$_o${1:-\"}";;
(140|42) set '\\'"\\$_o$1" ;;
(*) set "\\$_o$1" ;esac
done; printf "$1"; shift
done
done
eval '
ctbl(){
${1:+":"} return "$((OPTARG=0))"
set "" "" "${1%"${1#?}"}"
for c in ${a+"a=$a"} ${b+"b=$b"} ${c+"c=$c"}\
${LC_ALL+"LC_ALL=$LC_ALL"}
do while case $c in (*\'\''*) ;; (*) ! \
set "" "${c%%=*}='\''${c#*=}$1'\'' $2" "$3"
esac;do set "'"'\''\${c##*\'}"'$@"; c=${c%\'\''*}
done; done; LC_ALL=C a=$3 c=;set "" "$2 OPTARG='\''${#a}*("
while [ 0 -ne "${#a}" ]
do case $a in ([[:print:][:cntrl:]]*)
case $a in (['"$(printf \\1-\\77)"']*)
b=0;; (*) b=1
esac;; (['"$( printf \\200-\\277)"']*)
b=2;; (*) b=3
esac; set '"$(ctbl)"' "$@"
eval " set \"\${$((b+1))%"'\''"${a%"${a#?}"}"*}" "$6"'\''
a=${a#?};set "$((b=b*100+${#1}+${#1}/8*2)))" \
"$2(o$((c+=1))=$b)>=(d$c=$((0$b)))|"
done; eval " unset LC_ALL a b c;${2%?})'\''"
return "$((${OPTARG%%\**}-1))"
}'
Первый ctbl ()
- там вверху - выполняется только один раз. Он генерирует следующий вывод (который был отфильтрован с помощью sed -nl
для удобства печати) :
ctbl | sed -n l
"\200\001\002\003\004\005\006\a\b\t$
\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\
\035\036\037 !\\"#$%&'()*+,-./0123456789:;<=>?" "@ABCDEFGHIJKLMNOPQRS\
TUVWXYZ[\\]^_\\`abcdefghijklmnopqrstuvwxyz{|}~\177" "\200\201\202\203\
\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\
\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\
\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\
\267\270\271\272\273\274\275\276\277" "\300\301\302\303\304\305\306\
\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\
\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\
\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\
\372\373\374\375\376\377"$
... все 8-битные байты (меньше NUL
) , разделенный на четыре строки, заключенные в кавычки оболочки, равномерно разделенные по границам 64 байта. Строки могут быть представлены восьмеричными диапазонами, такими как \ 200 \ 1- \ 77
, \ 100- \ 177
, \ 200- \ 277
, \ 300- \ 377
, где байт 128 используется в качестве заполнителя для NUL
.
Вся цель существования первого ctbl ()
состоит в том, чтобы сгенерировать эти строки, чтобы eval
мог определить с ними вторую функцию ctbl ()
. буквально встроен после этого.Таким образом, на них можно ссылаться в функции без необходимости создавать их заново каждый раз, когда они нужны. Когда eval
действительно определяет вторую функцию ctbl ()
, первая перестает существовать.
Верхняя половина второй функции ctbl ()
здесь в основном вспомогательная - она предназначена для переносимой и безопасной сериализации любого текущего состояния оболочки, на которое оно может повлиять при вызове. Верхний цикл будет заключать в кавычки значения любых переменных, которые он может захотеть использовать, а затем складывает все результаты в свои позиционные параметры.
Первые две строки, однако, сначала сразу возвращают 0 и устанавливают $ OPTARG
в то же самое, если первый аргумент функции не содержит хотя бы одного символа. И если это так, вторая строка немедленно обрезает свой первый аргумент только до его первого символа - потому что функция обрабатывает только символ за раз. Важно отметить, что он делает это в текущем контексте локали, что означает, что если символ может содержать более одного байта, то при условии, что оболочка должным образом поддерживает многобайтовые символы, она не будет отбрасывать никакие байты, кроме тех, которые не находятся в первый символ его первого аргумента.
${1:+":"} return "$((OPTARG=0))"
set "" "" "${1%"${1#?}"}"
Затем он выполняет цикл сохранения, если это вообще необходимо, и после этого переопределяет текущий контекст языкового стандарта на языковой стандарт C для каждой категории, присваивая его переменной LC_ALL
.С этого момента символ может состоять только из одного байта, и поэтому, если в первом символе его первого аргумента было несколько байтов, теперь каждый из них должен быть адресован как отдельные символы самостоятельно.
LC_ALL=C
Именно по этой причине вторая половина функции представляет собой цикл while
, в отличие от однократной последовательности. В большинстве случаев он, вероятно, будет выполняться только один раз за вызов, но, если оболочка, в которой определен ctbl ()
, правильно обрабатывает многобайтовые символы, он может зацикливаться.
while [ 0 -ne "${#a}" ]
do case $a in ([[:print:][:cntrl:]]*)
case $a in (['"$(printf \\1-\\77)"']*)
b=0;; (*) b=1
esac;; (['"$( printf \\200-\\277)"']*)
b=2;; (*) b=3
esac; set '"$(ctbl)"' "$@"
Обратите внимание, что указанная выше подстановка команды $ (ctbl)
всегда оценивается только один раз - eval
, когда функция изначально определена, и что навсегда после этого токен заменяется на буквальный вывод этой подстановки команды, сохраненный в памяти оболочки. То же самое верно и для двух подстановок команд шаблона case
. Эта функция никогда не вызывает подоболочку или любую другую команду. Он также никогда не будет пытаться читать или записывать ввод / вывод (за исключением случая какого-либо диагностического сообщения оболочки, которое, вероятно, указывает на ошибку) .
Также обратите внимание, что проверка непрерывности цикла - это не просто [-n "$ a"]
, потому что, к моему разочарованию, по какой-то причине оболочка bash
делает:
char=$(printf \\1)
[ -n "$char" ] || echo but it\'s not null\!
but it's not null!
... и поэтому я явно сравниваю len $ a
с 0 для каждой итерации, которая также необъяснимо ведет себя по-разному (читай: правильно) .
Случай
проверяет первый байт на предмет включения в любую из наших четырех строк и сохраняет ссылку на набор байтов в $ b
. После этого первые четыре позиционных параметра оболочки устанавливаются
в строки, встроенные eval
и записанные предшественником ctbl ()
.
Затем все, что осталось от первого аргумента, снова временно обрезается до его первого символа -который теперь должен быть одним байтом. Этот первый байт используется в качестве ссылки для удаления из хвоста строки, которой он соответствует, а ссылка в $ b
- eval
'd для представления позиционного параметра, поэтому все, начиная с ссылочный байт на последний байт в строке может быть заменен. Остальные три строки полностью исключены из позиционных параметров.
eval " set \"\${$((b+1))%"'\''"${a%"${a#?}"}"*}" "$6"'\''
a=${a#?};set "$((b=b*100+${#1}+${#1}/8*2)))" \
"$2(o$((c+=1))=$b)>=(d$c=$((0$b)))|"
На этом этапе на значение байта (по модулю 64) можно ссылаться как на длину строки:
str=$(printf '\200\1\2\3\4\5\6\7')
ref=$(printf \\4)
str=${str%"$ref"*}
echo "${#str}"
4
Затем выполняется небольшая математика для согласования модуля на основе значения в $ b
, первый байт в $ a
навсегда удаляется, а вывод текущего цикла добавляется в ожидающий завершения стек перед повторным запуском цикла, чтобы проверить, является ли $ a
на самом деле пусто.
eval " unset LC_ALL a b c;${2%?})'\''"
return "$((${OPTARG%%\**}-1))"
Когда $ a
определенно пусто, все имена и состояние - за исключением $ OPTARG
, - что функция, на которую повлияла работа в ходе ее выполнения, восстанавливаются до своего предыдущего состояния - независимо от того, установлен ли он, а не null, установлен и равен нулю или не установлен - и вывод сохраняется в $ OPTARG
, когда функция возвращает. Фактическое возвращаемое значение на единицу меньше, чем общее количество байтов в первом символе его первого аргумента - поэтому любой однобайтовый символ возвращает ноль, а любой многобайтовый символ возвращает больше нуля - и его выходной формат немного странный.
Значение ctbl ()
сохраняет в $ OPTARG
является допустимым арифметическим выражением оболочки, которое при вычислении одновременно устанавливает имена переменных в форме $ o1
, $ d1
, $ o2
, $ d2
в десятичные и восьмеричные значения всех соответствующих байтов в первом символе его первого аргумента, но в конечном итоге вычисляются как общее количество байтов в его первом аргументе. Когда я писал это, я имел в виду особый рабочий процесс, и я думаю, что, возможно, стоит провести демонстрацию.
Я часто нахожу причину разделить строку с помощью getopts
, например:
str=some\ string OPTIND=1
while getopts : na -"$str"
do printf %s\\n "$OPTARG"
done
s
o
m
e
s
t
r
i
n
g
Я, вероятно, делаю немного больше, чем просто печатаю ее по символу в строке, но все возможно. В любом случае, я еще не нашел getopts
, который будет правильно выполнять (обратите внимание, что - dash
getopts
делает это char за char , но bash
определенно нет) :
str=ŐőŒœŔŕŖŗŘřŚśŜŝŞş OPTIND=1
while getopts : na -"$str"
do printf %s\\n "$OPTARG"
done| od -tc
0000000 305 \n 220 \n 305 \n 221 \n 305 \n 222 \n 305 \n 223 \n
0000020 305 \n 224 \n 305 \n 225 \n 305 \n 226 \n 305 \n 227 \n
0000040 305 \n 230 \n 305 \n 231 \n 305 \n 232 \n 305 \n 233 \n
0000060 305 \n 234 \n 305 \n 235 \n 305 \n 236 \n 305 \n 237 \n
0000100
Хорошо. Итак, я попробовал ...
str=ŐőŒœŔŕŖŗŘřŚśŜŝŞş
while [ 0 -ne "${#str}" ]
do printf %c\\n "$str" #identical results for %.1s
str=${str#?}
done| od -tc
#dash
0000000 305 \n 220 \n 305 \n 221 \n 305 \n 222 \n 305 \n 223 \n
0000020 305 \n 224 \n 305 \n 225 \n 305 \n 226 \n 305 \n 227 \n
0000040 305 \n 230 \n 305 \n 231 \n 305 \n 232 \n 305 \n 233 \n
0000060 305 \n 234 \n 305 \n 235 \n 305 \n 236 \n 305 \n 237 \n
0000100
#bash
0000000 305 \n 305 \n 305 \n 305 \n 305 \n 305 \n 305 \n 305 \n
*
0000040
Такой рабочий процесс - байт для байта / символ для типа char - я часто использую при выполнении tty-вещей. На переднем крае ввода вам нужно знать значения char, как только вы их читаете, и вам нужны их размеры (особенно при подсчете столбцов) , и вам нужно, чтобы символы были целыми символы.
Итак, теперь у меня есть ctbl ()
:
str=ŐőŒœŔŕŖŗŘřŚśŜŝŞş
while [ 0 -ne "${#str}" ]
do ctbl "$str"
printf "%.$(($OPTARG))s\t::\t$OPTARG\t::\t$?\t::\t\\$o1\\$o2\n" "$str"
str=${str#?}
done
Ő :: 2*((o1=305)>=(d1=197)|(o2=220)>=(d2=144)) :: 1 :: Ő
ő :: 2*((o1=305)>=(d1=197)|(o2=221)>=(d2=145)) :: 1 :: ő
Œ :: 2*((o1=305)>=(d1=197)|(o2=222)>=(d2=146)) :: 1 :: Œ
œ :: 2*((o1=305)>=(d1=197)|(o2=223)>=(d2=147)) :: 1 :: œ
Ŕ :: 2*((o1=305)>=(d1=197)|(o2=224)>=(d2=148)) :: 1 :: Ŕ
ŕ :: 2*((o1=305)>=(d1=197)|(o2=225)>=(d2=149)) :: 1 :: ŕ
Ŗ :: 2*((o1=305)>=(d1=197)|(o2=226)>=(d2=150)) :: 1 :: Ŗ
ŗ :: 2*((o1=305)>=(d1=197)|(o2=227)>=(d2=151)) :: 1 :: ŗ
Ř :: 2*((o1=305)>=(d1=197)|(o2=230)>=(d2=152)) :: 1 :: Ř
ř :: 2*((o1=305)>=(d1=197)|(o2=231)>=(d2=153)) :: 1 :: ř
Ś :: 2*((o1=305)>=(d1=197)|(o2=232)>=(d2=154)) :: 1 :: Ś
ś :: 2*((o1=305)>=(d1=197)|(o2=233)>=(d2=155)) :: 1 :: ś
Ŝ :: 2*((o1=305)>=(d1=197)|(o2=234)>=(d2=156)) :: 1 :: Ŝ
ŝ :: 2*((o1=305)>=(d1=197)|(o2=235)>=(d2=157)) :: 1 :: ŝ
Ş :: 2*((o1=305)>=(d1=197)|(o2=236)>=(d2=158)) :: 1 :: Ş
ş :: 2*((o1=305)>=(d1=197)|(o2=237)>=(d2=159)) :: 1 :: ş
Обратите внимание, что ctbl ()
на самом деле не определяет $ [od] [12 ...]
переменные - они никогда не имеют длительного эффекта ни на одно состояние, кроме $ OPTARG
- но только помещают строку в $ OPTARG
, которую можно использовать для определить их - так я получаю вторую копию каждого символа выше, выполняя printf "\\ $ o1 \\ $ o2"
, потому что они устанавливаются каждый раз, когда я оцениваю $ (($ OPTARG ))
. Но там, где я это делаю, я также объявляю модификатор длины поля для строкового аргумента % s
printf
], и поскольку выражение всегда оценивает общее количество байтов в символ, я получаю на выходе весь символ, когда делаю это:
printf %.2s "$str"
Если вы хотите распечатать десятичное представление значения UTF -8, я одобряю решение dsmsk80. Если, с другой стороны, вам нужно присвоить значение переменной, в Bash есть механизм printf
, который работает быстрее. Предположим, что вы хотите присвоить значение ascii "A" (, которое равно 65 в десятичной системе и которое мы присвоили переменнойtheChar
)переменной myVar
. Вставив функцию ord()
dmsmsk80, мы получим:
LC_CTYPE=C myVar=$(printf "%d" "'$theChar")
Чтобы это присвоение имело место, значение, полученное из '$theChar
, должно быть отформатировано в десятичных символах, а затем преобразовано из десятичного числа в число 65, которое затем сохраняется в myVar
. Чтобы избежать этого форматирования и синтаксического анализа, мы можем воспользоваться флагом -v
для printf
, который присваивает значение, которое будет напечатано напрямую. Синтаксис следующий:
LC_CTYPE=C printf -v myVar "%d" "'$theChar"
Я обнаружил это, потому что мне нужно было создать сценарий Bash, который давал мне хэш Fowler -Noll -Vo для каждой строки текстового файла, который я цитирую здесь:
#!/bin/bash
export LC_CTYPE=C
prime=16777619 #FNV prime
ofset=2166136261 #FNV offset
mask=0xffffffff #bitmask
cat $1 | while read line || [[ -n $line ]] #foreach line in file (w/o end return)
do
hash=$ofset #set hash to offset for line.
for (( i=0; i<${#line}; i++ )) #foreach char in line
do
printf -v charVal "%d" "'${line:$i:1}" #use printf -v trick.
hash=$(( ( ( hash ^ charVal ) * prime ) & mask )) #update FNV1-a hash for char.
done
printf "%08X\n" $hash #print hash result for line.
done
Использование опции -v
для назначения с помощью printf
привело к 50-кратному повышению производительности при запуске в Cygwin64.
"'A"
корректно тогда как, если Вы используете"A"
это скажет:A: invalid number
. Кажется, что это сделано на printf стороне (т.е., в оболочке,"'A"
действительно 2 символа, a'
и aA
. Они передаются printf. И в printf контексте, это преобразовывается в значение ASCII A, (и наконец печатается как десятичное число благодаря'%d'
. Использовать'Ox%x'
показать его в hexa или'0%o'
иметь его в восьмеричном)) – Olivier Dulac 26.09.2013, 14:05printf "\\$(printf '%03o' "$1")"
,'%03o'
,LC_CTYPE=C
и одинарная кавычка в"'$1"
? – razzak 04.12.2014, 21:42