Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm IT at my small firm; and, despite my dire warnings, everyone puts files on the server with awful names, including leading & trailing spaces, bad characters (including \ ; / + . < > - etc!)

They do this by accessing the (FreeBSD/FreeNAS) server via AFP on Macs, so no part of the system complains.

Is there a script I can use to go through an entire directory tree and fix bad filenames?

Basically replace all spaces & bad ASCII with _ ... and if a file already exists, just slap a _2 or something on the end.

I don't suppose there's a way to get the system to enforce good filenaming conventions, is there?

share|improve this question

closed as off topic by Ignacio Vazquez-Abrams, quanta, Iain Aug 21 '12 at 7:38

Questions on Server Fault are expected to relate to server, networking, or related infrastructure administration within the scope defined by the community. Consider editing the question or leaving comments for improvement if you believe the question can be reworded to fit within the scope. Read more about reopening questions here.If this question can be reworded to fit the rules in the help center, please edit the question.

You can't tell netatalk or whatnot to do this? – Ignacio Vazquez-Abrams Aug 20 '12 at 1:54
Actually, an even better question. Why do you believe that these characters are a problem? – Ignacio Vazquez-Abrams Aug 20 '12 at 1:57
The only things *nix doesn't like are / and \0. For everything else there's quotes. – Ignacio Vazquez-Abrams Aug 20 '12 at 2:04
@IgnacioVazquez-Abrams You are right in theory but the OS is not the only problem. There are (sadly) many scripts and programs that behave badly with spaces in file names. Of course these are bugs but having simple names can be useful to avoid problems. – Matteo Aug 20 '12 at 5:31
Please don't cross post questions to multiple Stackexchange sites. – Iain Aug 21 '12 at 7:39

You can get a list of them by using find / -iname with a pattern to match what you don't want to see (consider using a regular expression like [^:alnum:]). This, you can manipulate (eg. with sed) into a shell script that will use mv to rename the files.

Acceptable filenames are determined by the filesystem, so there may or may not be a way to enforce it without a cronjob.

share|improve this answer

@terdon has provided an elegant 1-line solution over at superuser:

SAVEIFS=$IFS; IFS=$(echo -en "\n\b"); \
for i in $(find . -type f  -name "*[\:\;\>\<\@\$\#\&\(\)\?\\\%\ ]*"); \
do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\\%\ ]/_}; done; IFS=$SAVEIFS

(Line breaks added for clarity; it's all one line.)

Alternatively, you can get more aggressive with something like

for i in $(find . -type f  -name "*[^0-9A-Za-z\_\.\-]*"); 

Full details here:

share|improve this answer

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