3

Struggling with this one and Googling it doesn't seem to be giving me solution that works.

I have a folder named...

file å?? name.txt

for example and to avoid problems, I want to rename it however I'm struggling to work out how. I've tried using ' ' and I also tried using \ before each special character e.g. 'file \å\?\? name \(2008\).txt' but I just get the following error...

-bash: cd: file \å\?\? name \(2008\).txt : No such file or directory

Is this improper use of \ or do I need an alternative approach?

Thanks

5
  • 1
    Does tab completion help e.g. typing mv file and then pressing the TAB key – steeldriver Nov 8 '15 at 0:28
  • @steeldriver I doubt that will help for non-printing chars which is almost certainly what the OP has. foo\r\r would appear as foo^M^M in the tab completion and that wouldn't work for removing it. – terdon Nov 8 '15 at 10:54
  • @terdon rm foo^M^M worked for me (that being what tab completion showed after touch $'foo\r\r' – muru Nov 10 '15 at 22:43
  • @muru huh, so it does, I stand corrected. Thanks. – terdon Nov 10 '15 at 22:49
5

The non-ASCII characters are not the problem, your shell can deal with å perfectly well. The issue is that your file is not actually named å??. If it were, rm 'å??' or even rm å?? would have worked.

You assume it's å?? because that's what ls shows, and that's a reasonable assumption, but ls will show various things as ?. For example:

$ mkdir "file å"\?\?" name.txt" "file å"$'\n'$'\n'" name.txt" "file å"$'\t'$'\t'" name.txt" "file å"$'\r'$'\r'" name.txt" "file å"$'\b'$'\b'" name.txt" "file å"$'\v'$'\v'" name.txt"

$ ls -l
total 24K
drwxr-xr-x 2 terdon users 4.0K Nov  8 13:02 file å?? name.txt
drwxr-xr-x 2 terdon users 4.0K Nov  8 13:02 file å?? name.txt
drwxr-xr-x 2 terdon users 4.0K Nov  8 13:02 file å?? name.txt
drwxr-xr-x 2 terdon users 4.0K Nov  8 13:01 file å?? name.txt
drwxr-xr-x 2 terdon users 4.0K Nov  8 13:02 file å?? name.txt
drwxr-xr-x 2 terdon users 4.0K Nov  8 13:02 file å?? name.txt

As you can see above, newlines, tabs, carriage returns, bells and vertical tabs (among others) are all shown as ?. Only the first file/directory of the ones created above actually has ? in its name. We can confirm this with ls -b:

$ ls -lb
total 24
drwxr-xr-x 2 terdon users 4096 Nov  8 13:02 file\ å??\ name.txt
drwxr-xr-x 2 terdon users 4096 Nov  8 13:02 file\ å\b\b\ name.txt
drwxr-xr-x 2 terdon users 4096 Nov  8 13:02 file\ å\t\t\ name.txt
drwxr-xr-x 2 terdon users 4096 Nov  8 13:01 file\ å\n\n\ name.txt
drwxr-xr-x 2 terdon users 4096 Nov  8 13:02 file\ å\v\v\ name.txt
drwxr-xr-x 2 terdon users 4096 Nov  8 13:02 file\ å\r\r\ name.txt

So, you can either run ls -b to get the right file name and then use ANSI C quoting to rename it:

mv å$'\r'$'\r' newname

Alternatively, you can use a glob to match all files/directories whose name starts with file å (note: this will only work if you just have one) :

mv "file å*" newname

Or, rename all files/directories whose name contains non alphanumeric characters (again, only useful for cases where you have a single such case):

shopt -s extglob  ## turn on extended globbing
mv !(*([[:graph:]])) newname

The strange !(*([[:graph:]])) needs some explaining. extglob enables extended globbing which lets us use !(foo) to match "not foo". The [[:graph:]] character class matches all printable characters (not tabs, newlines etc.) Therefore, the negated match !(*([[:graph:]])) will match all file/dirnames with non-printing characters.

If you need to deal with more than one such case, use a loop. Something like:

for dir in !(*([[:graph:]])); do 
     mv "$dir" "${dir//[^[:graph:]]/_}"; 
done

The ${dir//[^[:graph:]]/_} is the directory name with all non-printing characters replaced by _. The problem with this approach is that you can have different source directories which will end up with the same name (e.g. foo\n and foo\t will both become foo_). If that is a problem, just rename using a counter as well:

a=0; for dir in !(*([[:graph:]])); do 
    ((a++)); 
     mv "$dir" "${dir//[^[:graph:]]/_}$a"
done

That would result in:

drwxr-xr-x 2 terdon users 4096 Nov  8 13:08 file_å___name.txt1
drwxr-xr-x 2 terdon users 4096 Nov  8 13:08 file_å___name.txt2
drwxr-xr-x 2 terdon users 4096 Nov  8 13:08 file_å___name.txt3
drwxr-xr-x 2 terdon users 4096 Nov  8 13:08 file_å??_name.txt4
drwxr-xr-x 2 terdon users 4096 Nov  8 13:08 file_å___name.txt5
drwxr-xr-x 2 terdon users 4096 Nov  8 13:08 file_å___name.txt6
1
  • Thanks for this detailed response. Your initial point about ls -l not showing the actual name of the file or folder was my issue. This method worked for me. Nice to be able to do it this way but also good to know that Midnight Commander can dig me out of trouble if need be. Thanks for taking the time to do this. – spcurtis81 Nov 10 '15 at 19:04
0

Far as I understand you want to rename a file or folder that has non-English characters using terminal.

For this, you can use

mv x y

Where x is the name of the file/folder you want to rename and y is the new name you want for it.

If it has non-English characters and/or spaces then using ' ' to specify the limits of x and y should do. Here's an example:

mv 'öld namé öf fileş' 'néw namé öf fileş'

Please correct me if I misunderstood your question.

5
  • You understood my question correctly, thanks. I have tried the method you gave but strangely I received the no such file or directory error described in my original post. Not sure why it doesn't work. I did find a solution to this however by using midnight commander instead. Strange that the ' ' method doesn't work for my example though. – spcurtis81 Nov 8 '15 at 0:12
  • Weird. It should work. You used cd to the directory of the folder you want to rename right? – SarpSTA Nov 8 '15 at 0:13
  • The OP has already tried quoting and anyway, there's no need to quote non-English characters on a utf8 enabled terminal. Try touch τσουτσού && mv τσουτσού foo for example. – terdon Nov 8 '15 at 10:56
  • @terdon following the same method that OP tried I also faced a similar problem. Using quotes fixed my case. Please note that I didn't suggest it for the Non-Eng characters I suggested it for spacing which in my tests, solved the problem. When I want to rename "file å?? name.txt" to "τσουτσού ooo çaçaça" without using quotes I also get no such file or directory. Other than that I do realise that terminal's problem isn't that it can not recognize the characters. – SarpSTA Nov 8 '15 at 13:46
  • I understand that but, since the OP stated in the question that they had used quotes, and quotes in this case are only needed for the spaces, your answer didn't add anything not already mentioned in the question. – terdon Nov 8 '15 at 14:00
0

You clearly have attempted escaping and quoting, you can also use wildcards with annoying file names, e.g.,

$ ls *name\ 2008\ .txt    <==== make sure you only get the one file

$ mv *name\ 2008\ .txt  my_new_name.txt

If this doesn't meet your need, let me know -- there are other approaches using non-globbing.

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.