Я использую Ubuntu на машине с Windows 10. Я пытаюсь переименовать 5 файлов (file1.txt, file2.txt, file3.txt, file4.txt, file5.txt) так, чтобы каждый файл был заменен на Sample#_VoucherID.fastq.gz.
Для этого у меня есть .csv файл, который имеет формат oldfile,newfile
и я использую sed
следующим образом"
sed 's/^/mv -vi /;s/,/ / /;s/$//' < File-Rename. csv | bash -e
Всякий раз, когда я запускаю это, я вместо того, чтобы получить:
Sample#_VoucherID.fastq.gz
для каждого файла, я получаю 'Sample#_VoucherID.fastq.gz'$'\r'
вместо этого. Почему так происходит? Если я использую mv
просто в терминале Ubuntu для переименования файлов, я получаю файлы, переименованные так, как я хочу, без '
, $
и \r'
до и после имени файла. Если я не использую | bash -e
в файле и убираю кавычки, он печатает:
mv -vi file1.txt Sample1_VoucherID.fastq.gz
mv -vi file2.txt Sample2_VoucherID.fastq.gz
mv -vi file3.txt Sample3_VoucherID.fastq.gz
mv -vi file4.txt Sample4_VoucherID.fastq.gz
mv -vi file5.txt Sample5_VoucherID.fastq.gz
однако, на самом деле не выполняется команда mv
. Как я могу переименовать свои файлы, не получая этих дополнительных символов?
Это происходит из-за того, что ваш входной файл File-Rename.csv
имеет окончания строки CRLF в стиле Windows, а не в стиле Unix LF
- $ '\ r'
- это способ оболочки для представления символа возврата каретки.
Вы можете «исправить» свою команду, изменив окончательное выражение sed с s / $ //
(которое на самом деле ничего не делает - $
в регулярном выражении является утверждение нулевой длины, которое соответствует концу строки, но фактически не использует символ) в s / \ r $ //
В качестве альтернативы, конвертируйте входной файл с помощью dos2unix
ОДНАКО такой подход к переименованию файлов проблематичен - в частности, он не сработает, если старое или новое имя содержит пробелы или определенные специальные символы оболочки - и даже допускает внедрение кода 1 . Вместо этого я бы предложил что-то вроде
while IFS=, read old new; do
mv -vi -- "$old" "$new"
done < <(sed 's/\r$//' File-Rename.csv)
или
while IFS=, read old new; do
echo mv -vi -- "$old" "${new%$'\r'}"
done < File-Rename.csv
(удалите echo
, когда вас устраивают предложенные команды).
Обратите внимание, что этот подход сам по себе не работает для определенных имен, которые допустимы в формате CSV - в частности, тех, которые содержат заключенные в кавычки запятые (например, «foo, bar», baz
).
1 подумайте, что произойдет, если кто-то введет имя файла, например foo; rm *
, например