-eq: ожидается унарный оператор

Предполагая, что GNU dateиbash(или любая оболочка, которая выполняет замену с помощью<(...))и что данные хранятся в файле file, как и в первом примере данных в вопросе:

$ paste -d ' ' <( date -f <( cut -d ' ' -f1-3 file | tr ' ' '-' ) +"%Y %j" ) \
               <( cut -d ' ' -f4-5 file )
1980 001 0100 3.3
1982 101 0400 2.2
1985 338 0700 1.7
1995 365 1000 2.2
  • Первый cutиспользуется вместе с trдля преобразования дат в первых трех столбцах входных данных к форме YYYY-MM-DD.
  • Это передается в GNU dateдля пакетной обработки через его опцию -f. В качестве вывода мы запрашиваем даты, используя формат %Y %j. %Y— год в форме YYYYи %j— день года в форме DDD.
  • Это вставляется вместе с двумя последними столбцами из исходного файла (, созданного вторымcut)с использованием одного пробела в качестве разделителя.

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

-3
13.12.2017, 13:00
1 ответ

Хорошо, теперь, когда вы отредактировали свой вопрос, я думаю, что знаю, что происходит на самом деле.

Предположим, у меня есть каталог (~/dir), содержащий несколько файлов, и текстовый файл (~/file.txt), содержащий несколько имен файлов:

$ ls ~/dir
1.txt  2.txt  3.txt  4.txt  5.txt
$ cat ~/file.txt
1.txt
2.txt
3.txt
4.txt
5.txt

Насколько я знаю, ваш скрипт читает содержимое ~/file.txtи проверяет, существуют ли эти файлы (1.txt, 2.txtи т. д. )внутри ~/dir.

Но при запуске скрипта:

$ script.sh ~/dir ~/file.txt
/home/user/bin/script.sh: line 11: [: -eq: unary operator expected
All files present

Итак, что происходит? Посмотрите на этот фрагмент кода:

if [ ! -f "${1}/${file}" ]; # $1 is a path 
then 
    echo "$file is missing" 
    notok=$? 
fi

Основным недостатком здесь является то, что если содержимое как ~/dir, так и ~/file.txtсовпадает, echo "$file is missing"; notok=$?никогда не выполняется. Затем, если переменная notokне имеет значения, [ ${notok} -eq 0 ]терпит неудачу, потому что ${notok}расширяется до нуля (, как многие из нас подозревали ).

Этот недостаток не единственный, но именно он является причиной появления ошибки [: -eq: unary operator expected.

Как решить?

Если вы не хотите переписывать свой скрипт, просто инициализируйте notokпеременную любым числом, отличным от0перед вашим основным кодом. Например:

notok='1'

for file in `cat ${2}` #$2 is file.txt 
do 
    if [ ! -f "${1}/${file}" ]; # $1 is a path 
    then 
        echo "$file is missing" 
        notok=$? 
    fi 
done 
if [ ${notok} -eq 0 ]; 
then 
    echo "need to check" 
    exit 1 
else 
    echo "All files present" 
fi

Работает:

# When the content of ~/dir and ~/file.txt matches
$ ls ~/dir
1.txt  2.txt  3.txt  4.txt  5.txt
$ cat ~/file.txt
1.txt
2.txt
3.txt
4.txt
5.txt
$ script.sh ~/dir ~/file.txt
All files present

# When the content of ~/dir and ~/file.txt does not match
$ ls ~/dir
1.txt  2.txt  3.txt  4.txt  5.txt
$ cat ~/file.txt
foo
1.txt
2.txt
3.txt
4.txt
5.txt
$ script.sh ~/dir ~/file.txt
foo is missing
need to check

Но если бы мне пришлось переписывать сценарий, я бы сделал что-то вроде этого:

# Initialize variables
# It's possible to parse arguments like `-d DIR -f FILE` but let's keep simple
dir="${1}"
txt="${2}"
missing='0'

# Don't read lines with for!
while IFS='' read -r 'file'; do
  if [ ! -f "${dir}/${file}" ]; then
    echo "Missing file: ${file}"
    # Use a simple counter instead of catch the exit code of `echo`
    missing=$(( missing + 1 ))
  fi
done < "${txt}"

if [ "${missing}" -gt '0' ]; then
  echo "Total: ${missing}"
  exit '1'
else
  echo 'All files are present'
fi
0
28.01.2020, 05:19

Теги

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