I found, best to this moment, a solution when changing all those annoying filenames in large quantities, making them readable and easier to manipulate with in command-line.

So I found, among many commands, a little piece of software called detox. By default, it replaces spaces with _. Reading through manpages didn't gave me an anwser how to make detox rename files replacing spaces with -, instead.

[/] cd test
one five/  one four/  one one/  one three/  one two/
[test] detox *
[test] l
one_five/  one_four/  one_one/  one_three/  one_two/

How to do that?

I can't find .detoxrc file (or any of files related to this program) and if I create it, I don't know what to put in it.

P.S. Is there an alternative to detox?


It doesn't seem that detox has an option for that. It should be fairly simple to modify the source code to add a filter with your desired output (a small modification of the safe filter; don't forget to ensure that any leading - gets removed).

You could postprocess the result of detox, or use other tools altogether. There are many file renaming tools that are more flexible.

The Perl rename command (not to be confused with the util-linux rename command) supports transforming file names with arbitrary Perl code. This command is available as rename on Debian and derivatives (Ubuntu, Mint, …). It's available on Arch as perl-rename. If you just want to change _ into - and strip leading -, you can use:

rename 's/_/-/g; s/\A-*//' *

This only affects files (except dot files) in the current directory. To act on a directory recursively, combine this with the find command.

find . -depth -exec rename 's/_/-/g; s/\A-*//' {} +

Other features of detox can be expressed in Perl, most of them with the s/PATTERN/REPLACEMENT/ operator. For example, to retain only letters and digits and replace any sequence of other characters with -, you can use

rename 's/[^[:alnum:]]+/-/g; s/\A-//' …

If you want to approximate Unicode characters with ASCII, you can use Text::Unidecode:

perl -C -MText::Unidecode /usr/bin/rename '$_ = unidecode($_)' …

Another powerful renaming tool is the zmv command from the zsh shell. First run this (put it in your ~/.zshrc for interactive use):

autoload -U zmv

To change _ into - and strip leading -, you can use:

zmv '**/*' '$f:h/${${f##*/-#}//_/-}'

The pattern **/* makes this command act in subdirectories of the current directory recursively.

|improve this answer|||||
  • Currently, option rename 's/_/-/g; s/\A-*//' * works best for me. But, can you explain in short how to skip detox and replace not underscores, but spaces with dashes with this command? I don't understand it's structure, so I don't know how to change it. – Igor V. Apr 19 '15 at 12:57
  • @IgorVuckovic s/PATTERN/REPLACEMENT/ replaces PATTERN (a Perl regular expression) by REPLACEMENT. The g suffix means to replace all occurrences (without it, only the first is replaced). For example s/_/-/g replaces each _ by a -. s/[^[:alnum:]]/-/ replaces each non-alphanumeric character by a -. s/[^[:alnum:]]+/-/ replaces each sequence of non-alphanumeric characters by a single -. s/ +/-/ replaces each sequence of spaces by a -. A \A at the beginning of the pattern means that the replacement is carried out at the beginning of the name only. – Gilles 'SO- stop being evil' Apr 19 '15 at 13:02

At least as of detox version 1.2.0, the filtering can be customized (the following commands/locations may need to be changed depending on your distro). Firstly:

cp /usr/share/detox/safe.tbl ~/mysafe.tbl

Next edit the file mysafe.tbl searching for the word "space" (around line 127) and change the underscore to a hyphen.

Now modify ~/.detoxrc e.g. as follows:

sequence hyphenated {
   safe {filename "/home/MY_USSERNAME/mysafe.tbl";};
   #wipeup {remove_trailing;};

(Replace "MY_USERNAME" of course...)

Now run the following command:

detox -vs hyphenated *

and you should be good to go :)

Edit 20170801: Detox seems to have some UTF-8 problems. Have created a few patches, emailed upstream and debian maints, now have to open a bug on some site called "github" or something - time to figure it out...

|improve this answer|||||

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.