From 1e28cc156076eb9b52a2c1941819ef52b9a6f444 Mon Sep 17 00:00:00 2001 From: Antoine Stevan <44101798+amtoine@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:00:10 +0100 Subject: [PATCH] add a "bulk rename" command to the stdlib candidates (#643) i received an archive with files with integer ids in their names (1, 2, ...) but because these ids had no padding, the files were completely out of order when sorting... e.g. 9 comes after 10 because 1 comes before 9 as a character :thinking: i wrote a command to rename a bulk of files in a directory with a closure :yum: i was not really sure where to put it, so i created `stdlib-candidate/fs.nu` :+1: --- stdlib-candidate/fs.nu | 84 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 stdlib-candidate/fs.nu diff --git a/stdlib-candidate/fs.nu b/stdlib-candidate/fs.nu new file mode 100644 index 00000000..70b3fc4e --- /dev/null +++ b/stdlib-candidate/fs.nu @@ -0,0 +1,84 @@ +# rename a bulk of files in a directory using a closure +# +# the reason behind this command is quite simple +# - sometimes one receives a bunch of files with integer ids: 1, 2, 3, ... +# - these ids come rarely with padding... i.e. 1 instead of 001 when there are 3-digit ids +# - this means that file with id 9 will be sorted way after file with id 1000 +# +# this command allows to do such a task! +# +# # Examples +# rename files in `/foo` with a name that has an id to have 3 digits with 0-padding +# > file bulk-rename /foo { +# parse "some_format_{id}" +# | get 0 +# | update id { fill --alignment r --character 0 --width 3 } +# | $"some_format_($in.id)" +# } +export def "file bulk-rename" [ + directory: path, # the path where files need to be renamed in bulk + stem_update: closure, # the code to run on the stem of the files: should start with parsing the format and end with reconstructing the same format + --verbose, # be verbose when moving the files around +]: nothing -> nothing { + ls --full-paths $directory | insert new { + get name | path parse | update stem $stem_update | path join + } + | each { + if $verbose { + mv --force --verbose $in.name $in.new + } else { + mv --force $in.name $in.new + } + } + + null +} + +#[test] +def test [] { + use std assert + + let test_dir = $nu.temp-path | path join (random uuid) + + mkdir $test_dir + seq 1 10 | each {|i| touch ($test_dir | path join $"some_($i)_format.txt") } + + let expected = [ + "some_10_format.txt", + "some_1_format.txt", + "some_2_format.txt", + "some_3_format.txt", + "some_4_format.txt", + "some_5_format.txt", + "some_6_format.txt", + "some_7_format.txt", + "some_8_format.txt", + "some_9_format.txt", + ] + let actual = glob $"($test_dir)/*" | str replace $test_dir "" | str trim --left --char "/" + assert equal ($actual | sort) $expected + + file bulk-rename $test_dir { + parse "some_{i}_format" + | get 0 + | update i { fill --alignment r --character 0 --width 3 } + | $"some_($in.i)_format" + } + + let expected = [ + "some_001_format.txt", + "some_002_format.txt", + "some_003_format.txt", + "some_004_format.txt", + "some_005_format.txt", + "some_006_format.txt", + "some_007_format.txt", + "some_008_format.txt", + "some_009_format.txt", + "some_010_format.txt", + ] + let actual = glob $"($test_dir)/*" | str replace $test_dir "" | str trim --left --char "/" + assert equal ($actual | sort) $expected + + rm -rf $test_dir +}