Puncte:0

De ce redenumirea fișierelor cu sed și mv se imprimă „$”\r”

drapel ke

Folosesc Ubuntu pe o mașină cu Windows 10. Încerc să redenumesc 5 fișiere (fișier1.txt, fișier2.txt, fișier3.txt, fișier4.txt, fișier5.txt) astfel încât fiecare fișier să fie înlocuit cu Sample#_VoucherID.fastq.gz.

Pentru a face acest lucru, am un fișier .csv care are un format de fişier vechi, fişier nou si eu folosesc sed după cum urmează"

sed 's/^/mv -vi /;s/,/ /;s/$//' < File-Rename.csv | bash -e

Ori de câte ori rulez asta, în loc să obțin:

Sample#_VoucherID.fastq.gz pentru fiecare fișier, primesc „Sample#_VoucherID.fastq.gz'$'\r' in schimb. De ce se întâmplă asta? Daca folosesc mv doar în terminalul Ubuntu pentru a redenumi fișierele, primesc fișierele redenumite așa cum vreau, fără ',$,și \ înainte și după numele fișierului. Dacă nu folosesc | bash -e în fișier și elimin ghilimelele, se tipărește:

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

cu toate acestea, nu rulează de fapt mv comanda. Cum îmi pot redenumi fișierele fără a obține acele caractere suplimentare?

drapel cn
Deoarece fișierul File-Rename.csv are sfârșituri de linie `\r\n` în stil DOS. Folosiți `dos2unix` pe el sau faceți `sed -e 's/\r$//' -e 'codul dvs. aici'`
Puncte:2
drapel hr

Acest lucru se întâmplă deoarece fișierul dvs. de intrare File-Rename.csv are terminații de linie CRLF în stil Windows în loc de stil Unix LF - cel $'\r' este modul shell-ului de a reprezenta caracterul de întoarcere a căruciorului.

Puteți „corecta” comanda dumneavoastră schimbând expresia sed finală de la s/$// (care de fapt nu face nimic - $ într-o expresie regulată este o afirmație de lungime zero care se potrivește cu sfârșitul liniei, dar nu consumă de fapt un caracter) la s/\r$//

Alternativ, convertiți fișierul de intrare folosind dos2unix

CU toate acestea, această abordare a redenumirii fișierelor este problematică - în special, va eșua dacă numele vechi sau cel nou conține spații sau anumite caractere speciale shell - și chiar permite injectarea de cod.1. În schimb, aș sugera ceva de genul

în timp ce IFS=, citește vechi nou; do 
  mv -vi -- „$vechi” „$nou”
terminat < <(sed 's/\r$//' File-Rename.csv)

sau

în timp ce IFS=, citește vechi nou; do 
  echo mv -vi -- "$vechi" "${nou%$'\r'}"
done < File-Rename.csv

(înlăturați ecou odată ce ești mulțumit de comenzile propuse).

Rețineți că această abordare însăși va eșua pentru anumite nume care sunt legale în formatul CSV - în special cele care conțin virgule încorporate între ghilimele ("foo,bar",baz de exemplu).


1 gândiți-vă ce se întâmplă dacă cineva introduce un nume de fișier ca foo;rm * de exemplu

Justin avatar
drapel ke
Mulțumesc! Asta a funcționat! Doar pentru cunoștințele mele, ce a făcut `s/\r$\`? Se spune să înlocuiești `CRLF` cu nimic? Asta a funcționat! Nu folosesc spații, așa că am folosit prima sugestie, dar voi ține cont și de codul `while` pe care îl trimiteți. Apreciez asta!
drapel hr
@Justin da, așa e - `sed 's/\r$//'` se potrivește cu un caracter de întoarcere car `\r` ancorat la sfârșitul unei linii `$` și nu înlocuiește nimic în locul lui. Probabil că ați putea șterge în siguranță *toate* returnările de transport (de exemplu, cu `tr -d '\r'`), dar versiunea sed este mai corectă din punct de vedere formal pentru a transforma `CRLF` în `LF`
Justin avatar
drapel ke
Mulțumesc; este foarte util pentru că de câte ori am încercat să folosesc `dos2unix` nu a ajutat; deci cunoașterea codurilor alternative precum le-ați dat este grozavă. Apreciez că ți-ai făcut și tu timp pentru a explica codul!

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.