I'm trying to write a loop for a script that checks a specific directory for any special characters and moves those files to a specific directory (except spaces and hyphens - those are simply replaced with underscores and kept in that directory and I've gotten that script done). I've looked at several possibilities that I've found here and on Stack overflow which are close matches, but I can't quite get any of them to work like I need to.

    for i in /home/*; do

            case $i in
                 *\?*||*\**||*\$*||*\%*||*\.*||*\'*||*\"*||*\**||*\,* )
            mv home/failed;


It doesn't have to be anything like this if there's a shorter or better way to accomplish this.

Thanks in advance, you guys are great! I've learned more practical info from scouring Stack Overflow, U&L, etc than a BS in IT taught me.

  • 3
    How about mv -f *[\?\*\$\%\.\,\"\']* failed/ ?
    – doneal24
    Commented May 6, 2016 at 15:54
  • Should this replace the entire case? I tried simply replacing the "mv" line and both the special characters and mv line and it didn't work as I'd hoped.
    – SomeGuy
    Commented May 6, 2016 at 16:06
  • It worked! Thanks!...... Noob question, but how do I mark yours as the answer?
    – SomeGuy
    Commented May 6, 2016 at 16:11
  • A fair question. In this case yes, because the software I'm using it for can only accept underscores, 0-9, a-z.
    – SomeGuy
    Commented May 6, 2016 at 16:13
  • I was being lazy, I suppose - it accepts all alphanumeric characters [A-Z] &[a-z] and underscores. Not periods though, because periods indicate another specific purpose :)
    – SomeGuy
    Commented May 6, 2016 at 16:18

2 Answers 2


The thing to be careful of here is that unix filenames can contain characters with any 8-bit character value except '/' and '\0'.

If you want to move any file that has a character that is not in [A-Z] or [a-z] or an underscore, use the following:

for file in /home/*; do
    [ -n "${filename//[A-Za-z_]/}" ] && mv "$file" failed/

It works by first removing the directory path, leaving just the filename. Then it strips out all 'legal' characters from the filename. If any characters remain, then the filename contains an illegal character, and will be moved.


This should be able to be modified to use in a script but if you were doing it from command line you can do ls -i. This will give the inode for each file in the directory. From that you can use find:

find ./ -i $INODE -exec mv {} <target> \;

  • How does this select files with special characters in their names? Are you suggesting that the user should run the ls -i, manually identify the specified files by visual inspection, and then run the find command for each inode number? Commented May 7, 2016 at 0:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .