I am trying to change all characters that are not letters, numbers, dashes, dots, or underscores to an underscore in file names in a directory. So far I have the following:
ls *.mp3 | sed 's/[^0-9a-zA-Z._-]/_/g'
This works except that it just shows me the results, it does not actually change the names. What else do I need to do to get it to change the names?
答案1
Don't parse Ls. That seems to work well, but for complex cases it may fail.
With Bash's parameter expansion:
for f in *.mp3; do mv -- "$f" "${f//[!0-9a-zA-Z.-]/_}"; done
With Rename:
rename -- 's/[^0-9a-zA-Z.-]/_/g' *.mp3
If you only have standard POSIX tools and assuming no newline characters in the file names,
for f in *.mp3; do
mv -- "$f" "$(printf '%s\n' "$f" | sed 's/[^0-9a-zA-Z.-]/_/g')"
done
答案2
With zsh
:
autoload -Uz zmv # best in ~/.zshrc
zmv '(*).mp3' '${f//[^0-9a-zA-Z_.-]/_}'
In zsh
, ranges are based on codepoint value, so 0-9
includes 0123456789 only (and not 0123456789٠١٢٣٤٥٦٧٨۰۱۲۳۴۵۶۷۸߀߁߂߃߄߅߆߇߈०१२३४५६७८০১২৩৪৫৬৭৮੦੧੨੩੪੫੬੭੮૦૧૨૩૪૫૬૭૮୦୧୨୩୪୫୬୭୮௦௧௨௩௪௫௬௭௮౦౧౨౩౪౫౬౭౮౸౹౺౻౼౽౾೦೧೨೩೪೫೬೭೮൦൧൨൩൪൫൬൭൮෦෧෨෩෪෫෬෭෮๐๑๒๓๔๕๖๗๘໐໑໒໓໔໕໖໗໘༠༡༢༣༤༥༦༧༨༪༫༬༭༮༯༰༱༳၀၁၂၃၄၅၆၇၈႐႑႒႓႔႕႖႗႘፩፪፫፬፭፮፯፰០១២៣៤៥៦៧៨៰៱៲៳៴៵៶៷៸᠐᠑᠒᠓᠔᠕᠖᠗᠘᥆᥇᥈᥉᥊᥋᥌᥍᥎᧐᧑᧒᧓᧔᧕᧖᧗᧘᧚᪀᪁᪂᪃᪄᪅᪆᪇᪈᪐᪑᪒᪓᪔᪕᪖᪗᪘᭐᭑᭒᭓᭔᭕᭖᭗᭘᮰᮱᮲᮳᮴᮵᮶᮷᮸᱀᱁᱂᱃᱄᱅᱆᱇᱈᱐᱑᱒᱓᱔᱕᱖᱗᱘⁰⁴⁵⁶⁷⁸₀₁₂₃₄₅₆₇₈⅐⅑⅒⅓⅔⅕⅖⅗⅘⅙⅚⅛⅜⅝⅞⅟ↅ↉①②③④⑤⑥⑦⑧⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳⑴⑵⑶⑷⑸⑹⑺⑻⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒌⒍⒎⒏⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛⓪⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴⓵⓶⓷⓸⓹⓺⓻⓼⓾⓿❶❷❸❹❺❻❼❽❿➀➁➂➃➄➅➆➇➉➊➋➌➍➎➏➐➑➓〇〡〢〣〤〥〦〧〨㉈㉉㉊㉋㉌㉍㉎㉏㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿㋀㋁㋂㋃㋄㋅㋆㋇㋉㋊㋋㍘㍙㍚㍛㍜㍝㍞㍟㍠㍢㍣㍤㍥㍦㍧㍨㍩㍪㍫㍬㍭㍮㍯㍰㏠㏡㏢㏣㏤㏥㏦㏧㏩㏪㏫㏬㏭㏮㏯㏰㏱㏲㏳㏴㏵㏶㏷㏸㏹㏺㏻㏼㏽㏾꘠꘡꘢꘣꘤꘥꘦꘧꘨꣐꣑꣒꣓꣔꣕꣖꣗꣘꤀꤁꤂꤃꤄꤅꤆꤇꤈꧐꧑꧒꧓꧔꧕꧖꧗꧘꧰꧱꧲꧳꧴꧵꧶꧷꧸꩐꩑꩒꩓꩔꩕꩖꩗꩘꯰꯱꯲꯳꯴꯵꯶꯷꯸012345678