-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f08b5d1
commit 16f4f94
Showing
9 changed files
with
9 additions
and
9 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
{"componentChunkName":"component---src-templates-article-tsx-content-file-path-src-articles-06-bash-cmds-01-mp-3-tag-md","path":"/articles/bash_cmds/mp3_tag/","result":{"data":{"mdx":{"body":"\n```bash\nfind . -name '*.mp3' \\\n -printf 'echo $(exiftool -json \"%p\" | jq -r .[0].Track | python3 -c \"print(str(int(input())).rjust(3, \\\\\"0\\\\\"))\") \"-\" ' \\\n -printf '$(exiftool -json \"%p\" | jq -r .[0].Title) | ' \\\n -printf 'mv \"%p\" \"%h/$(tee).mp3\" && ' \\\n -printf 'echo \"%p\" \\n' | \\\n sh\n```\n\nOk, let me break this down for you:\n```bash\nfind . -name '*.mp3' -printf '%p'\n```\nget's all files ending with `.mp3` (and directories too but I didn't bother adding `-type f` to exclude them).\nThen it prints something for each file (without adding newlines between the files).\n`%p` gets replaced by the file's path.\n\nInstead of just printing the file name we print multiple commands that get piped into sh.\nEach one consists of two parts plus a cherry on top.\n\n## The First Part\nBash replaces `$(some_cmd)` with the output of `some_cmd`.\nTherefore\n```bash\necho $(exiftool -json \"%p\" | jq -r .[0].Track | python3 -c \"print(str(int(input())).rjust(3, \\\\\"0\\\\\"))\") \"-\"\n```\nexpands to the output of that big concoction plus the little dash after the last brace.\nIn bash pipes, denoted by `|`, take the output of the left-hand command and input it into the right-hand one.\nThis is used to get all the metadata of our MP3 file in JSON format (`exiftool -json \"%p\"`) and extract the track number with `jq -r .[0].Track`.\n\nBut we want to pad that number to always have three digits (`007` instead of `7`).\nThere are thousands of different ways to do that but I didn't bother looking them up and settled for probably the most complicated one:\nWe're going to use Python!\n```bash\npython3 -c 'print(\"Hello World\")'`\n```\nruns\n```python\nprint(\"Hello World\")\n```\nSo\n```bash\npython3 -c \"print(str(int(input())).rjust(3, \\\"0\\\"))\"\n```\nruns (`\\\"` gets escaped to `\"`)\n```python\nprint(str(int(input())).rjust(3, \"0\"))\n```\nwhich does the padding in a very, very bad way.\nBut we're not here to do clean stuff, we're here to bodge.\nTo make this run in the `-printf` flag, we have to escape the `\\` (which we used to escape the `\"`) with another `\\`.\n\n### The First Part, Part Two\n```bash\n-printf '$(exiftool -json \"%p\" | jq -r .[0].Title) | ' \\\n```\nDoes the same as what we've just seen but with the song title, which doesn't require our Python <s>bodge</s> magic.\n\nSo the entire first part prints out `007 - song name`.\n\n## The Second Part\nNow we want to use this to name our MP3 file.\nTherefore we pipe the first part's output into mv.\nBut mv doesn't support pipes like that so we have to spill some tee.\nI'm terribly sorry, I mean `$(tee)`.\nThe tee command does a lot of stuff but for all intents and purposes it just prints out whatever is piped into it.\n\nSo\n```bash\n-printf 'mv \"%p\" \"%h/$(tee).mp3\"'\n```\nfirst replaces `%p` with the file's original path and `%h` with the path to the directory the file is located in.\nThen `$(tee).mp3` get's replaced with the output of our echo command plus the file extension.\nSo it changes the name to `007 - song name.mp3`.\n\n## The Cherry on Top\nOnce all that has been done,\n```bash\n-printf 'echo \"%p\" \\n'\n```\nensures that after mv did it's business, the file path get's printed to the console, so that the user knows something is happening.\nAnd it also adds a linebreak in the end so that sh executes one command at a time.\n\n# To Put it in a Nutshell\nsh executes a list of commands that got printf-ed by find.\nIn the end these commands change the name of a file to something else.\nAnd that something else got created by echo, which is printing a string that bash expands to the track number, a `-` and a string that bash expands to the song title.\nBash does that by cleaning up the output of exiftool.\nThis cleaning up is in turn being partially performed by python3, which runs a tiny Python script.\n\nPretty easy, isn't it?\nGetting this one-liner to work with files that include `'` and/or `\"` is left as an exercise to the reader.\n\nOh and it might also delete files without a track number, maybe try fixing that too.\n\n","frontmatter":{"date":"Wednesday, October 12, 2022","title":"Bodging MP3 Names in Bash","description":" Why do it properly when a Bash one-liner does it too? ","banner":"/social_banner/bash_cmds.png","version":"1.0.0"}}},"pageContext":{"id":"4babb8e9-1394-5b33-96d9-9db996bc7fc2","frontmatter":{"type":"article","title":"Bodging MP3 Names in Bash","description":" Why do it properly when a Bash one-liner does it too? ","banner":"/social_banner/bash_cmds.png","thumb":"../../../static/social_banner/bash_cmds.png","slug":"bash_cmds/mp3_tag","date":"2022-10-12T00:00:00.000Z","listed":true,"version":"1.0.0"}}},"staticQueryHashes":["1995789189","2480137602","475732191"],"slicesMap":{}} | ||
{"componentChunkName":"component---src-templates-article-tsx-content-file-path-src-articles-06-bash-cmds-01-mp-3-tag-md","path":"/articles/bash_cmds/mp3_tag/","result":{"data":{"mdx":{"body":"\n```bash\nfind . -name '*.mp3' \\\n -printf 'echo $(exiftool -json \"%p\" | jq -r .[0].Track | python3 -c \"print(str(int(input())).rjust(3, \\\\\"0\\\\\"))\") \"-\" ' \\\n -printf '$(exiftool -json \"%p\" | jq -r .[0].Title) | ' \\\n -printf 'mv \"%p\" \"%h/$(tee).mp3\" && ' \\\n -printf 'echo \"%p\" \\n' | \\\n sh\n```\n\nOk, let me break this down for you:\n```bash\nfind . -name '*.mp3' -printf '%p'\n```\nget's all files ending with `.mp3` (and directories too but I didn't bother adding `-type f` to exclude them).\nThen it prints something for each file (without adding newlines between the files).\n`%p` gets replaced by the file's path.\n\nInstead of just printing the file name we print multiple commands that get piped into sh.\nEach one consists of two parts plus a cherry on top.\n\n## The First Part\nBash replaces `$(some_cmd)` with the output of `some_cmd`.\nTherefore\n```bash\necho $(exiftool -json \"%p\" | jq -r .[0].Track | python3 -c \"print(str(int(input())).rjust(3, \\\\\"0\\\\\"))\") \"-\"\n```\nexpands to the output of that big concoction plus the little dash after the last brace.\nIn bash pipes, denoted by `|`, take the output of the left-hand command and input it into the right-hand one.\nThis is used to get all the metadata of our MP3 file in JSON format (`exiftool -json \"%p\"`) and extract the track number with `jq -r .[0].Track`.\n\nBut we want to pad that number to always have three digits (`007` instead of `7`).\nThere are thousands of different ways to do that but I didn't bother looking them up and settled for probably the most complicated one:\nWe're going to use Python!\n```bash\npython3 -c 'print(\"Hello World\")'`\n```\nruns\n```python\nprint(\"Hello World\")\n```\nSo\n```bash\npython3 -c \"print(str(int(input())).rjust(3, \\\"0\\\"))\"\n```\nruns (`\\\"` gets escaped to `\"`)\n```python\nprint(str(int(input())).rjust(3, \"0\"))\n```\nwhich does the padding in a very, very bad way.\nBut we're not here to do clean stuff, we're here to bodge.\nTo make this run in the `-printf` flag, we have to escape the `\\` (which we used to escape the `\"`) with another `\\`.\n\n### The First Part, Part Two\n```bash\n-printf '$(exiftool -json \"%p\" | jq -r .[0].Title) | ' \\\n```\nDoes the same as what we've just seen but with the song title, which doesn't require our Python <s>bodge</s> magic.\n\nSo the entire first part prints out `007 - song name`.\n\n## The Second Part\nNow we want to use this to name our MP3 file.\nTherefore we pipe the first part's output into mv.\nBut mv doesn't support pipes like that so we have to spill some tee.\nI'm terribly sorry, I mean `$(tee)`.\nThe tee command does a lot of stuff but for all intents and purposes it just prints out whatever is piped into it.\n\nSo\n```bash\n-printf 'mv \"%p\" \"%h/$(tee).mp3\"'\n```\nfirst replaces `%p` with the file's original path and `%h` with the path to the directory the file is located in.\nThen `$(tee).mp3` get's replaced with the output of our echo command plus the file extension.\nSo it changes the name to `007 - song name.mp3`.\n\n## The Cherry on Top\nOnce all that has been done,\n```bash\n-printf 'echo \"%p\" \\n'\n```\nensures that after mv did it's business, the file path get's printed to the console, so that the user knows something is happening.\nAnd it also adds a linebreak in the end so that sh executes one command at a time.\n\n# To Put it in a Nutshell\nsh executes a list of commands that got printf-ed by find.\nIn the end these commands change the name of a file to something else.\nAnd that something else got created by echo, which is printing a string that bash expands to the track number, a `-` and a string that bash expands to the song title.\nBash does that by cleaning up the output of exiftool.\nThis cleaning up is in turn being partially performed by python3, which runs a tiny Python script.\n\nPretty easy, isn't it?\nGetting this one-liner to work with files that include `'` and/or `\"` is left as an exercise to the reader.\n\nOh and it might also delete files without a track number, maybe try fixing that too.\n\n","frontmatter":{"date":"Wednesday, October 12, 2022","title":"Bodging MP3 Names in Bash","description":" Why do it complicated when a Bash one-liner does it too? ","banner":"/social_banner/bash_cmds.png","version":"1.0.0"}}},"pageContext":{"id":"4babb8e9-1394-5b33-96d9-9db996bc7fc2","frontmatter":{"type":"article","title":"Bodging MP3 Names in Bash","description":" Why do it complicated when a Bash one-liner does it too? ","banner":"/social_banner/bash_cmds.png","thumb":"../../../static/social_banner/bash_cmds.png","slug":"bash_cmds/mp3_tag","date":"2022-10-12T00:00:00.000Z","listed":true,"version":"1.0.0"}}},"staticQueryHashes":["1995789189","2480137602","475732191"],"slicesMap":{}} |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.