[/b/] [/d/] [/tu/] [/a/] [/ph/] [/wa/] [/cg/] [/t/] [/p/]

[Burichan] [Foliant] [Futaba] [Greenhell] [Gurochan] [Photon] - [Home] [Manage] [Archive]

[Return]
Posting mode: Reply
Leave these fields empty (spam trap):
Name
Link
Subject
Comment
File
Verification
Password (for post and file deletion)
  • Supported file types are: GIF, JPG, PDF, PNG
  • Maximum file size allowed is 30720 KB.
  • Images greater than 200x200 pixels will be thumbnailed.

File: 1654673193265.jpg -(25134 B, 277x300) Thumbnail displayed, click image for full size.
25134 No.201585  
#!/bin/sh
CR=$(printf '\r')
# file name: timestamp
filename=$(date +%s)
IFS="$CR"
read -r delim # field delimiter boundary
read -r disp # Content-Disposition header
IFS=
# skip leading empty lines
while read -r line; do
[ -z "$line" ] && break
[ "$line" = "$CR" ] && break
done
# save received text into the $filename
IFS="$CR"
while read -r line; do
[ "$line" = "$delim"-- ] && break
echo "$line"
done > $filename
IFS=

Это немного модифицированный кот из busybox/networking/http_post_upload.cgi.
Вопрос. Как взять текст из нескольких полей? В цикле на 10-й строке проверка равенства "$line" = "$delim" не срабатывает.
В приложенном zip.jpg рабочее файлохламилище, кот почти такой же. Но файлы принимаются, опять же, по одному.

>> No.201587  

Я чёт такое на авк писал.

>Как взять текст из нескольких полей?

В цикле и проверять content-length, ради тестов сделай себе echo.cgi.

>> No.201596  

>>201587

> ради тестов сделай себе echo.cgi

Сделал.

cat > data
env > vars
printf 'HTTP/1.1 303 See Other\r\n'
printf 'Location: /\r\n\r\n'
>> No.201600  
#!/bin/sh
delim=--${CONTENT_TYPE#multipart/form-data; boundary=}
echo $delim > _delim # dbg
CR=$(printf '\r')
while read line; do
[ "$line" = "$delim"-- ] && break
[ "$line" = "$delim" ] && continue
IFS="$CR"
read -r disp
name=${disp#Content-Disposition: form-data; name=\"}
name=${name%?}
IFS=
while read -r _; do # ?
[ -z "$_" ] && break
[ "$_" = "$CR" ] && break
done
IFS="$CR"
while read -r _; do
[ "$line" = "$delim" ] && break
[ "$line" = "$delim"-- ] && break
echo "$_"
done > $name
IFS=
done
printf 'HTTP/1.1 303 See Other\r\n'
printf 'Location: /\r\n\r\n'

Вот. Почему-то не выходит из первого внутреннего цикла, всё до конца сохраняется в один файл. Никак не могу взять в толк, почему же.

>> No.201601  
#!/bin/sh
delim="--${CONTENT_TYPE#multipart/form-data; boundary=}"
CR=$(printf '\r')
save() {
IFS="$CR"
read -r disp
name=${disp#Content-Disposition: form-data; name=\"}
name=${name%?}
IFS=
while read -r _; do
[ -z "$_" ] && break
[ "$_" = "$CR" ] && break
done
IFS="$CR"
while read -r _; do
[ "$_" = "$delim" ] && save
[ "$_" = "$delim"-- ] && exit 0
echo "$_"
done > $name
}
IFS="$CR"
while read -r line; do
[ "$line" = "$delim" ] && save
[ "$line" = "$delim"-- ] && exit 0
done
IFS=
printf 'HTTP/1.1 303 See Other\r\n'
printf 'Location: /\r\n\r\n'

Удобные они, текстовые протоколы, всё-таки. Кажется, я победил.

>> No.201602  
File: 1654699489172.jpg -(382931 B, 1024x1124) Thumbnail displayed, click image for full size.
382931

Спасибо, Новерь, без тебя бы ничего не вышло.

>> No.201657  
File: 1654921850951.jpg -(2005962 B, 4096x2924) Thumbnail displayed, click image for full size.
2005962

С текстовыми полями получается, а вот картинки сохранить — нетривиальная загогулина. Юниксовые программы (или мои о них знания) плохо подходят для обработки бинарных данных.
Проще будет так: сохранить весь запрос, пришедший с файлового инпута multiple в один файл, просто cat. Затем выпарсить отдельные файлы, но:
while read _ ... echo или printf — не подойдёт, испортит данные;
dd не катит — размер каждого из файлов неизвестен;
Нужно как-то найти разделитель, потом следующий, и сохранить то, что между ними. Я бы такую утилиту на сишке написал, но это не чистое решение.
>>201587

> проверять content-length

Он один для всего запроса, а не для каждого из файлов. Почему это не добавили в CGI наряду с MIME-типом, я не знаю, было бы гораздо проще.
Получается типа того…

-----------------------------29995809218093749221856446032^M
Content-Disposition: form-data; name="file1"; filename="..."^M
Content-Type: application/octet-stream^M
^M <--------- headers end with empty line
file contents
file contents
file contents
^M <--------- extra empty line
-----------------------------29995809218093749221856446032--^M

Вот если б только было

Content-Type: application/octet-stream; length="N"^M

!

>> No.201658  

>>201657
пошто панцу порвал дорогие же

>> No.201867  
# usage:
# filescount /path/to/dir/* # count all files
# filescount /path/to/dir/*/ # count all directories
filescount() {
[ -e "$1" ] \
&& printf '%s\n' "$#" \
|| printf '%s\n' 0
}

Чтобы без $(ls -1 /path/to/dir | wc -l).

>> No.201868  

>>201867

`find /path/to/dir -type f | wc -l`
`find /path/to/dir -type d | wc -l`

?

>> No.201869  

>>201868
Если нужно посчитать файлы нерекурсивно, то можно обойтись без дополнительных процессов же. Здесь «файлы» — всё, кроме .., . и остальных скрытых. То есть, каталоги тоже.
Если рекурсивно, то будет вроде того

recursive_filescount() {
for f in $@; do
[ -f "$f" ] && i=$((i+1))
[ -d "$f" ] && recursive_filescount "$f"/*
done
}
i=0
recursive_filescount path/to/dir
printf '%s\n' $i
>> No.201921  

>>201869

#!/bin/sh    
recursive_filescount() {
for f in $@; do
[ -f "$f" ] && i=$((i+1))
[ -d "$f" ] && recursive_filescount "$f"/*
done
}
if [ ! -d "$1" ]
then
echo "'$1' is not directory"
fi
i=0
recursive_filescount "$1"
echo "$i"
>> No.201922  

>>201869
Алсо, он не считает директории у тебя.

>> No.201925  

>>201922
Второй, рекурсивный, и не должен — там для этого проверка. Он в некоторых местах ошибается, даёт результат меньший чем find | wc -l.

>> No.201927  

>>201925
Дело было в скрытых файлах и каталогах. find их обрабатывает, * — пропускает. Ещё и "$@" нужно закавычивать.

#!/bin/sh
recursive_filescount() {
for f in "$@"; do
[ -f "$f" ] && i=$((i+1))
[ -d "$f" ] && recursive_filescount "$f"/*
done
}
[ ! -d "$1" ] && echo "'$1': not a directory" 2>&1
i=0
recursive_filescount "$1"
echo $i
>> No.201930  

>>201927
shopt -s dotglob

>> No.201931  

>>201927
Алсо, зачем 2>&1? И почему exit не добавил в if [ ! -d ... ]? Я забыл просто.

>> No.201934  
File: 1655997858105.jpg -(52183 B, 798x437) Thumbnail displayed, click image for full size.
52183

>>201931

> зачем 2>&1?

Не зачем, а почему — от невысыпания.

> почему exit не добавил в if [ ! -d ... ]?

Мне показалось, ты решил так, что один файл есть — значит, не авария.

>>201930

> shopt -s dotglob

Это уже не POSIX. Есть только в bash, zsh (shopt -s globdots).

>> No.201936  

>>201934

>Мне показалось, ты решил так, что один файл есть — значит, не авария.

На самом деле так и было, но как-то не имеет смысла.

>Это уже не POSIX

А GLOBIGNORE? Если он посиксный, то можно через .* и GLOBIGNORE='.:..' сделать.

>> No.206504  
File: 1666737544733.jpg -(89047 B, 899x899) Thumbnail displayed, click image for full size.
89047

https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/utilities/head.html
https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/utilities/tail.html

> POSIX
> tail -c
> tail -c +10
> no "head -c"
>> No.207101  

Вместо head/tail нельзя ли использовать sed или awk? Покрайней мере что-то вроде sed -n 1,3p покрасивее.

>> No.207103  
File: 1666796040668.jpg -(707515 B, 1254x1771) Thumbnail displayed, click image for full size.
707515

>>207101
Думаю там возмущение было по поводу отсуствия у posix head опции -c, из-за чего для вывода первых n байт файла нужно использовать tail -c +n, что ни разу не интуитивно. В gnu версии head эта опция уже есть. Ну а в качестве замены можно и dd использовать.

>> No.207165  

>>207103
"tail -c+n" не выводит первые байты, а пропускает: "tail -c+32" начинает вывод с 32-го байта и далее до конца. Это ещё более неинтуитивно.
Очень странно. И в новой редакции (2017) его тоже нет.

> Ну а в качестве замены можно и dd использовать.

Придётся. Если писать скрипты для всех юниксов сразу.
>>207101
Использование "sed 10q" заместо "head" — целый мем.

>> No.207167  
File: 1666915457143.jpg -(42803 B, 852x480) Thumbnail displayed, click image for full size.
42803

Это мелочи по сравнению с тем, что в стандарте нету mount — TRUE-POSIX-OS не сможет загрузиться.

>> No.214750  

Ломающие новости! Аргументы в начале скрипта можно обрабатывать не только лесенкой if'ов.
case $# in

1) foo="$1" ;;
2) foo="$1"; bar="$2" ;;
*) usage ;;

esac
К тому же, в кейзах допустимы шаблоны — что и доказывает дефолтное правило сверху, со звёздочкой.
case "$1" in

[0-9]) n=$1 ;;
[a-z]) usage ;;

esac



Delete Post []
Password

[/b/] [/d/] [/tu/] [/a/] [/ph/] [/wa/] [/cg/] [/t/] [/p/]