Файл не отправляется по ftp - ошибка: "Параметр неверный"

В этом ответе есть решения для любого типа файлов. С новыми строками или пробелами.
Есть решения для недавнего bash, а также для древнего bash и даже для старых оболочек posix.

Дерево, указанное ниже в этом ответе [1] , используется для тестов.

выберите

Легко заставить selectработать либо с массивом:

$ dir='deep/inside/a/dir'
$ arr=( "$dir"/* )
$ select var in "${arr[@]}"; do echo "$var"; break; done

Или с позиционными параметрами:

$ set -- "$dir"/*
$ select var; do echo "$var"; break; done

Таким образом, единственная реальная проблема состоит в том, чтобы получить «список файлов» (, правильно разделенный )внутри массива или внутри позиционных параметров. Продолжай читать.

баш

Я не вижу проблемы с bash, о которой вы сообщаете. Bash может выполнять поиск внутри заданного каталога:

$ dir='deep/inside/a/dir'
$ printf '<%s>\n' "$dir"/*
<deep/inside/a/dir/directory>
<deep/inside/a/dir/file>
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/zz last file>

Или, если вам нравится петля:

$ set -- "$dir"/*
$ for f; do printf '<%s>\n' "$f"; done
<deep/inside/a/dir/directory>
<deep/inside/a/dir/file>
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/zz last file>

Обратите внимание, что приведенный выше синтаксис будет корректно работать с любой (разумной )оболочкой (не csh по крайней мере ).

Единственное ограничение приведенного выше синтаксиса — переход в другие каталоги.
Но Баш мог это сделать:

$ shopt -s globstar
$ set -- "$dir"/**/*
$ for f; do printf '<%s>\n' "$f"; done
<deep/inside/a/dir/directory>
<deep/inside/a/dir/directory/file>
<deep/inside/a/dir/directory/file name>
<deep/inside/a/dir/directory/file with a
newline>
<deep/inside/a/dir/directory/zz last file>
<deep/inside/a/dir/file>
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/zz last file>

Чтобы выбрать только некоторые файлы (, подобные тем, которые заканчиваются в файле ), просто замените*:

$ set -- "$dir"/**/*file
$ printf '<%s>\n' "$@"
<deep/inside/a/dir/directory/file>
<deep/inside/a/dir/directory/zz last file>
<deep/inside/a/dir/file>
<deep/inside/a/dir/zz last file>

прочный

Когда вы размещаете в заголовке «пространство-сейф », я предполагаю, что вы имели в виду «надежный ».

Самый простой способ быть устойчивым к пробелам (или символам новой строки )— отказаться от обработки ввода, содержащего пробелы (или символы новой строки ).Очень простой способ сделать это в оболочке — выйти с ошибкой, если любое имя файла расширяется пробелом. Есть несколько способов сделать это, но наиболее компактным (и posix )(, но ограниченным содержимым одного каталога, включая имена suddirectories и избегая точечных -файлов ), является:

$ set -- "$dir"/file*                            # read the directory
$ a="$(printf '%s' "$@" x)"                      # make it a long string
$ [ "$a" = "${a%% *}" ] || echo "exit on space"  # if $a has an space.
$ nl='
'                    # define a new line in the usual posix way.  

$ [ "$a" = "${a%%"$nl"*}" ] || echo "exit on newline"  # if $a has a newline.

Если используемое решение надежно в любом из этих пунктов, удалите тест.

В bash вложенные каталоги -можно было протестировать сразу с помощью описанного выше **.

Существует несколько способов включения точечных файлов, решение Posix:

set -- "$dir"/* "$dir"/.[!.]* "$dir"/..?*

найти

Если по какой-либо причине необходимо использовать find, замените разделитель на NUL (0x00 ).

Баш 4.4+

$ readarray -t -d '' arr < <(find "$dir" -type f -name file\* -print0)
$ printf '<%s>\n' "${arr[@]}"
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/directory/file name>
<deep/inside/a/dir/directory/file with a
newline>
<deep/inside/a/dir/directory/file>
<deep/inside/a/dir/file>

Баш 2.05+

i=1  # lets start on 1 so it works also in zsh.
while IFS='' read -d '' val; do 
    arr[i++]="$val";
done < <(find "$dir" -type f -name \*file -print0)
printf '<%s>\n' "${arr[@]}"

POSIXLY

Чтобы сделать правильное решение POSIX, в котором find не имеет разделителя NUL и нет ни -d(, ни-a)для чтения, нам нужен совершенно другой подход.

Нужно использовать комплекс -execfrom find с вызовом шелла:

find "$dir" -type f -exec sh -c '
    for f do
        echo "<$f>"
    done
    ' sh {} +

Или, если требуется select (select является частью bash, а не sh):

$ find "$dir" -type f -exec bash -c '
      select f; do echo "<$f>"; break; done ' bash {} +

1) deep/inside/a/dir/file name
2) deep/inside/a/dir/zz last file
3) deep/inside/a/dir/file with a
newline
4) deep/inside/a/dir/directory/file name
5) deep/inside/a/dir/directory/zz last file
6) deep/inside/a/dir/directory/file with a
newline
7) deep/inside/a/dir/directory/file
8) deep/inside/a/dir/file
#? 3
<deep/inside/a/dir/file with a
newline>

[1] Это дерево (\012 — это новые строки):

$ tree
.
└── deep
    └── inside
        └── a
            └── dir
                ├── directory
                │   ├── file
                │   ├── file name
                │   └── file with a \012newline
                ├── file
                ├── file name
                ├── otherfile
                ├── with a\012newline
                └── zz last file

Можно построить с помощью этих двух команд:

$ mkdir -p deep/inside/a/dir/directory/
$ touch deep/inside/a/dir/{,directory/}{file{,\ {name,with\ a$'\n'newline}},zz\ last\ file}
0
14.06.2019, 11:28
1 ответ

Как предположил @Kusalanada, Windows не понравился символ " :"

Я изменил имя файла с

file_2019-06-11_14:54:37.tar
с

по

file_02019-06-11_145437.tar
1
28.01.2020, 02:40

Теги

Похожие вопросы