I have hundreds of directories, some nested in other directories, with tens of thousands of files. The files need to have a date/time stamp removed from them.

An example filename is Letter to Client 27May2016~20160531-162719.pdf and I would like for it to go back to being Letter to Client 27May2016.pdf

Another example filename is ABCDEF~20160531-162719 and I would like for it to go back to being ABCDEF. Note that this file has no extension, unlike the example above.

I need a command that I can run at the root of the affected folders that will recursively go through and find/fix the filenames.

( I use Syncthing to sync files, and restored deleted files by copying them from the .stversions directory back to where they were, but found that Syncthing appends that date/time stamp...)

  • 1
    What OS are you working on? (That can limit the tools available to you) – Jeff Schaller Dec 11 '17 at 18:19

Meet the Perl rename tool:

$ rename -n -v  's/~[^.]+//' *~*
rename(ABCDEF~20160531-162719, ABCDEF)
rename(Letter to Client 27May2016~20160531-162719.pdf, Letter to Client 27May2016.pdf)

(online man page, also see this Q)

That regex says to match a tilde, as many characters that are not dots, but at least one; and to replace whatever matched with an empty string. Remove the -n to actually do the replace. We could change the pattern to ~[-0-9]+ to just replace digits and dashes.

Sorry, you said "recursively", so lets use find:

$ find -type f -name "*~*" -execdir  rename -n -v  's/~[-0-9]+//' {} +
rename(./ABCDEF~20160531-162719, ./ABCDEF)
rename(./Letter to Client 27May2016~20160531-162719.pdf, ./Letter to Client 27May2016.pdf)

Or just with Bash or ksh, though directories with ~ followed by digits will break this:

$ shopt -s extglob       # not needed in ksh (as far as I can tell)
$ shopt -s globstar      # 'set -o globstar' in ksh
$ for f in **/*~* ; do 
    echo mv -- "$f" "$g" 
mv -- ABCDEF~20160531-162719 ABCDEF
mv -- Letter to Client 27May2016~20160531-162719.pdf Letter to Client 27May2016.pdf

Again, remove the echo to actually do the rename.

  • The Debian / Ubuntu man pages for it call it prename(1). The man page is pretty bare-bones, though. – Peter Cordes Dec 12 '17 at 4:12
  • @PeterCordes, it's rename(1p) in my Debian, and apparently on Ubuntu online manpages too – ilkkachu Dec 12 '17 at 7:35

In bash:

shopt -s globstar
for file in **/*~[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]*
  echo mv -- "$file" "${file/~[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]/}"

This finds all filenames (recursively) that match the date pattern (following a tilde), then echoes a sample mv command to rename them. The target of the mv command is the result of a bash parameter expansion that replaces any tilde-datestring text with nothing.



echo "ABCDEF~20160531-162719" | sed "s/~.*//g"
echo "Letter to Client 27May2016~20160531-162719.pdf" |sed "s/~.*[^.pdf]//g"

Above commands achieves the mentioned result

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.