Я работаю над сценарием оболочки для работы, который должен позволить мне найти каталог на основе 5- или 6-значного номера, который использует наша система, и скопировать файл из этого каталога. Я бы сделал это вручную, но мне нужно получить более 3000 записей из примерно 3 ТБ доступных данных.

Вот проблема, с которой я сталкиваюсь. Часть моего скрипта использует find, и когда я запускаю его, скрипт вставляет '\r' перед подстановочным знаком, который я вставил в скрипт. Я пытался экранировать его с помощью \, цитируя его, но ничего, что я сделаю, не позволит мне использовать подстановочный знак в этой команде. Я процитировал мой код ниже.

#!/bin/bash

export IFS="\n"

cat $1 | while read -r LINE
do
    #Change directory to root of necessary files.
    cd /volume1/Backup/CMS_Data/CLIENT\ DATA\ COPY/

    echo "Current Directory"
    pwd

    #Get directory needed based on current line
    CLAIM="$(find $LINE\*/documents/ -type d)"

    #Change to directory based on claim number.
    echo $CLAIM

done

Ниже приведен результат, который я получаю.

find: `48668\r*/documents/': No such file or directory

Я не могу найти что-либо о побеге или о том, как его обойти. Есть идеи, что вызывает это?

3 ответа3

0

Файл, который вы передаете как $1 имеет \r\n символы новой строки. Ваш $IFS равен \n , поэтому \r остается последним символом $LINE .

Используйте dos2unix для конвертации файла.

0

Казалось бы, есть несколько способов исправить это. Возможно, самым простым способом было бы исправить переменную $ LINE, чтобы отбрасывать любые нечисловые символы. Вы можете сделать это, добавив следующую строку перед строкой, начинающей CLAIM =

  LINE=${LINE//[!0-9]//}

В зависимости от вашего ввода вам может потребоваться изменить строку CLAIM на CLAIM = "$(найдите $ LINE/ */ documents/ -type d)"

Альтернативным решением было бы изменить вашу первую строку, чтобы отфильтровать возврат каретки на входе - вы можете изменить его на что-то вроде

 tr -d "\r" < $1 | while read -r LINE
0

Другой способ очистить возврат каретки от ввода - воспользоваться функцией команды read , которая удаляет начальные и конечные пробелы из того, что они читают. Просто переопределите IFS (в основном, определение пробела в оболочке), чтобы включить \r , например:

... while IFS=$' \t\n\r' read -r LINE ...

Обратите внимание, что поскольку определение IFS является префиксом команды read , оно применяется только к этой одной команде и не будет портить другие вещи (или позже потребуется установить его в нормальное состояние).

Кстати, ваше переопределение IFS в начале довольно проблематично, так как обратный слеш не рассматривается как выход в данной конкретной ситуации, поэтому вы фактически определили \ и n в качестве пробельных символов. Это может иметь действительно странные эффекты. Я рекомендую просто оставить это в покое.

Некоторые другие рекомендации: cat чтобы прочитать файл; это бессмысленно. Просто перенаправьте ввод, вот так:

while IFS=$' \t\n\r' read -r LINE
do
    ...
done <"$1"

Кроме того, почти всегда неплохо помещать двойные кавычки вокруг ссылок на переменные (как я делал выше для $2), чтобы избежать странных артефактов синтаксического анализа. То же самое относится и к $LINE . О, и я бы также порекомендовал избегать имен переменных, начинающихся с заглавных букв; Есть множество из них с особым значением, и легко случайно использовать один из них и получить странные результаты. Гораздо безопаснее использовать имена переменных в нижнем или смешанном регистре.

Наконец, я рекомендую всегда добавлять проверку ошибок в команду cd в сценариях, так как в случае неудачи остальная часть сценария будет выполняться в неожиданном месте с возможно странными результатами. Что-то вроде этого:

cd /volume1/Backup/CMS_Data/CLIENT\ DATA\ COPY/ || {
    echo "Error changing directory to CLIENT DATA COPY; giving up" >&2
    exit 1
}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .