A common problem. You have a music album, say, it contains the following files:
drwxr-x--- 2 i i 4096 Jun 13 12:25 covers -rwxr-x--- 1 i i 17495062 Oct 17 2019 Morton Feldman - Rothko Chapel + Why Patterns - 01 - Rohtko Chapel 1.mp3 -rwxr-x--- 1 i i 8804855 Oct 17 2019 Morton Feldman - Rothko Chapel + Why Patterns - 02 - Rothko Chapel 2.mp3 -rwxr-x--- 1 i i 5663474 Oct 17 2019 Morton Feldman - Rothko Chapel + Why Patterns - 03 - Rothko Chapel 3.mp3 -rwxr-x--- 1 i i 8911852 Oct 17 2019 Morton Feldman - Rothko Chapel + Why Patterns - 04 - Rothko Chapel 4.mp3 -rwxr-x--- 1 i i 5533906 Oct 17 2019 Morton Feldman - Rothko Chapel + Why Patterns - 05 - Rothko Chapel 5.mp3 -rwxr-x--- 1 i i 56636104 Oct 17 2019 Morton Feldman - Rothko Chapel + Why Patterns - 06 - Why Patterns.mp3 -rwxr-x--- 1 i i 444 Oct 17 2019 Morton Feldman - Rothko Chapel + Why Patterns .m3u -rwxr-x--- 1 i i 926 Oct 17 2019 Rothko Chapel + Why Patterns.CUE -rwxr-x--- 1 i i 2401 Oct 17 2019 Rothko Chapel + Why Patterns .log
Filenames are too long, which is nuisance, for mp3-players, etc. You want to make them shorter. Here I wrote an utility to do so:
% racket remove_LCP_from_files.rkt *.mp3 (path relative old-fname Morton Feldman - Rothko Chapel + Why Patterns - 01 - Rohtko Chapel 1.mp3 new-fname: 1 - Rohtko Chapel 1.mp3) (path relative old-fname Morton Feldman - Rothko Chapel + Why Patterns - 02 - Rothko Chapel 2.mp3 new-fname: 2 - Rothko Chapel 2.mp3) (path relative old-fname Morton Feldman - Rothko Chapel + Why Patterns - 03 - Rothko Chapel 3.mp3 new-fname: 3 - Rothko Chapel 3.mp3) (path relative old-fname Morton Feldman - Rothko Chapel + Why Patterns - 04 - Rothko Chapel 4.mp3 new-fname: 4 - Rothko Chapel 4.mp3) (path relative old-fname Morton Feldman - Rothko Chapel + Why Patterns - 05 - Rothko Chapel 5.mp3 new-fname: 5 - Rothko Chapel 5.mp3) (path relative old-fname Morton Feldman - Rothko Chapel + Why Patterns - 06 - Why Patterns.mp3 new-fname: 6 - Why Patterns.mp3)
It removed this common prefix: "Morton Feldman - Rothko Chapel + Why Patterns - 0":
And the result:
-rwxr-x--- 1 i i 17495062 Oct 17 2019 1 - Rohtko Chapel 1.mp3 -rwxr-x--- 1 i i 8804855 Oct 17 2019 2 - Rothko Chapel 2.mp3 -rwxr-x--- 1 i i 5663474 Oct 17 2019 3 - Rothko Chapel 3.mp3 -rwxr-x--- 1 i i 8911852 Oct 17 2019 4 - Rothko Chapel 4.mp3 -rwxr-x--- 1 i i 5533906 Oct 17 2019 5 - Rothko Chapel 5.mp3 -rwxr-x--- 1 i i 56636104 Oct 17 2019 6 - Why Patterns.mp3 -rwxr-x--- 1 i i 444 Oct 17 2019 Morton Feldman - Rothko Chapel + Why Patterns .m3u -rwxr-x--- 1 i i 926 Oct 17 2019 Rothko Chapel + Why Patterns.CUE -rwxr-x--- 1 i i 2401 Oct 17 2019 Rothko Chapel + Why Patterns .log
This will also work:
% racket remove_LCP_from_files.rkt */*.mp3
Directories supported as well.
The source code:
#lang racket
(require srfi/13)
(require file/glob)
; todo: dry run?
; because the standard "min" function takes values in argument...
(define (min-in-list l)
(apply min l))
(define (strings-prefix-length l)
(min-in-list (map (lambda (x) (string-prefix-length (first x) (second x))) (cartesian-product l l))))
;(strings-prefix-length (list "hello" "hell" "he can"))
;(strings-prefix-length (list "qhello" "whell" "the can"))
;(strings-prefix-length (list "hello" "hello" "hello"))
(define cmd (current-command-line-arguments))
(when (= (vector-length cmd) 0)
(displayln "usage: racket remove_LCP_from_files.rkt *.mp3")
(displayln "or: ... path/*.mp3")
(exit))
(define files '())
(for ([p cmd])
(let-values ([(p-path p-filename p-something) (split-path p)])
(set! files (cons (path->string p-filename) files))))
(when (eq? (length files) 0)
(displayln "no files collected")
(exit))
(when (eq? (length files) 1)
(displayln "only a single file. not enough.")
(exit))
(define chop-characters-from-each-filename (strings-prefix-length files))
(when (eq? chop-characters-from-each-filename 0)
(displayln "no common prefix")
(exit))
(for ([p cmd])
(let-values ([(p-path p-filename p-something) (split-path p)])
(let ([new-fname (substring (path->string p-filename) chop-characters-from-each-filename)])
(displayln (list "path" p-path "old-fname" p-filename "new-fname:" new-fname))
(if (eq? p-path 'relative)
; we are inside the path
(rename-file-or-directory
p-filename
new-fname)
(rename-file-or-directory
(build-path p-path p-filename)
(build-path p-path new-fname))))))

Yes, I know about these lousy Disqus ads. Please use adblocker. I would consider to subscribe to 'pro' version of Disqus if the signal/noise ratio in comments would be good enough.