summaryrefslogtreecommitdiff
path: root/posts
diff options
context:
space:
mode:
author53hornet <atc@53hor.net>2021-10-02 17:22:43 -0400
committer53hornet <atc@53hor.net>2021-10-02 17:22:43 -0400
commit19969f79632e4936073dcd91fbd9dfbe917e9438 (patch)
treed17fe2095c20c2fa6274f99ae1c4a83e69bd31a6 /posts
parente0e45f0697ea0858fbea34cffc824f80105e8d7f (diff)
download53hor-19969f79632e4936073dcd91fbd9dfbe917e9438.tar.xz
53hor-19969f79632e4936073dcd91fbd9dfbe917e9438.zip
published file renaming with vim
Diffstat (limited to 'posts')
-rw-r--r--posts/2021-09-26-useful-shell-scripting-and-bulk-renaming-files-with-vim.php41
1 files changed, 41 insertions, 0 deletions
diff --git a/posts/2021-09-26-useful-shell-scripting-and-bulk-renaming-files-with-vim.php b/posts/2021-09-26-useful-shell-scripting-and-bulk-renaming-files-with-vim.php
new file mode 100644
index 0000000..bc88caa
--- /dev/null
+++ b/posts/2021-09-26-useful-shell-scripting-and-bulk-renaming-files-with-vim.php
@@ -0,0 +1,41 @@
+<?php
+$title = "Useful Shell Scripting and Bulk Renaming Files with Vim";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ I used to use <code>vifm</code>, a terminal file manager, on FreeBSD and Linux. I realized the only feature I was really using was bulk interactive file renaming with <code>vim</code>. So I ditched the file manager altogether and implemented the bulk rename feature in a few lines of shell.
+</p>
+
+<p>
+ Lots of terminal file managers have this feature (<code>lf</code>, <code>vifm</code>, <code>ranger</code>), and I tried a bunch but always ended up going back to just <code>cd</code>-ing around in the terminal and opening files most of the time. The only feature that did keep me using file managers/browsers/explorers was the bulk rename. For example, in <code>vifm</code>, you can select a bunch of files and open all of their names in a Vim buffer, one per line. You make a bunch of bulk changes or one-offs, and then save and quit. All of the files get renamed to whatever their line changed to. Since this was the only feature I was using I decided to implement it myself with just a little useful shell scripting.
+</p>
+
+<p>
+<pre>
+<code>
+rename() {
+ src="$(mktemp -t rename)" # Make a temp file for source filenames
+ dst="$(mktemp -t rename)" # Make a temp file for destination filenames
+ printf '%s\n' "$@" | tee "$src" > "$dst" # Write args (filenames) into temp files
+ $EDITOR "$dst" # Edit the destination filenames
+ diff -s "$src" "$dst" > /dev/null || paste "$src" "$dst" | sed -e "s/\t/' '/" -e "s/^/mv -i '/" -e "s/$/'/" | sh
+ # Change the source filenames into destination filenames by rewriting as mv commands
+}
+</code>
+</pre>
+
+<p>
+ Here's the function! That's all there is to it. It reads in a list of filenames from the args and writes them all to two temporary files. It then opens an editor and lets you interactively rename files (by hand, with regexes, macros, etc.). Then you save and quit your editor and (as long as the old and new names are different), generates <code>mv</code> commands to rename everything. It pipes those commands to a shell.
+</p>
+
+<p>
+ I could have alternatively read files from STDIN but I chose to use args so that I could more easily make use of shell globbing and wildcards. It makes more sense to make my <code>rename</code> tool take arguments the way that <code>cp</code> and <code>mv</code> do.
+</p>
+
+<p>
+ I've been using this renaming extensively, especially for tagging TV show DVD rips. It's so handy I just put it in my shell's startup aliases. I also uninstalled <code>vifm</code>, the file manager I had been using for just this purpose.
+</p>