Литеральный ответ: Pipe Through!
Если вы не сообщите dos2unix
имя файла, с которым он работает, он не сможет изменить этот файл на месте.
while IFS= read -r line; do
echo "No carriage returns here: <$line>"
done < <(dos2unix <"$file")
Перенаправления выполняются оболочкой до запуска программы. Когда вы вызываете dos2unix <input.txt
, оболочка заменяет дескриптор файла 0 дескриптором чтения на input.txt
перед вызовом dos2unix
без аргументов.
Если вы хотите быть действительно параноиком (и заплатить за производительность за эту паранойю), вы можете предотвратить гипотетическое несуществующее dos2unix, которое изменило файловый дескриптор, полученный на stdin ввместо этого сделайте его <(cat <"$file" | dos2unix)
таким, чтобы dos2unix
считывал данные из FIFO, подключенного к отдельному исполняемому файлу cat
, а не прямо из входного файла.Само собой разумеется, я никогда не советую это на практике.
Лучший ответ: Не
Вам не нужно dos2unix
(что -со стандартным поведением модификации на месте - предназначено для интерактивных пользователей, а не для сценариев);сама оболочка может отбрасывать для вас возврат каретки:
#!/usr/bin/env bash
# ^^^^- not /bin/sh; needed for $'' syntax and [[ ]]
while IFS= read -r line || [[ $line ]]; do
line=${line%$'\r'}
echo "No carriage returns here: <$line>"
done <"$file"
${var%expr}
- это расширение параметра , которое удаляет любой конечный экземпляр выражения glob expr
из содержимогопеременной var
. $'\r'
- это ANSI C-подобная строка синтаксис для возврата каретки.Использование этого синтаксиса важно, потому что другие вещи, которые выглядят так, как будто они могут ссылаться на возврат каретки не .
\r
вне контекста цитирования любого вида, - это простобуква r
. "\r"
или '\r'
- это два символа (обратная косая черта, а затем буква r
), а не возврат каретки.
[[ $line ]]
- расширение ksh, принятое bash, эквивалентное [ -n "$line" ]
;он проверяет, является ли переменная line
непустой.read
может возвращать false при заполнении строки, если у вас есть частичная строка без какого-либо ограничителя;как указывает l0b0, линейные разделители вместо терминаторы являются общими для Windows.Это обеспечивает обработку последней строки файла, даже если она не заканчивается новой строкой.