1

I want to use cp to copy a file named with Chinese characters to my fat32 usb stick. This is done using a script, so using nautilus is not a solution for me. I do not want to rename the files, too. I receive an error cp: cannot create regular file '测试.pdf': Invalid argument. On Ubuntu, the cp command works perfectly.

The locale:
LANG=en_US.UTF-8 LC_NUMERIC=en_GB.UTF-8 LC_TIME=en_GB.UTF-8 LC_MONETARY=en_GB.UTF-8 LC_PAPER=en_GB.UTF-8 LC_MEASUREMENT=en_GB.UTF-8

The USB stick is formatted using:
sudo mkfs.vfat -n $volume_name /dev/$dev_name

Then I create mount directory:
sudo mkdir /run/media/piotr/$volume_name

And then the USB stick is mounted:
sudo mount /dev/$dev_name /run/media/piotr/$volume_name

  • 1
    Please add the locale info of the shell and mount options of your FAT32 – 炸鱼薯条德里克 Sep 26 '18 at 3:06
1

I'm going to give you a few meta-answers.

First up, (just for background) FAT32 handles UTF-8/UTF-16 filenames in an odd way.

More than likely, it's just a mount option (covered below)... just in case it's not though I'm covering a few other options...

Step 1: Check your mount options.

When I tried to mount a vfat filesystem in Fedora, these were the options presented:

$ grep vfat /proc/mounts
/dev/loop0 /tmp/tmp.Migr78uZ75 vfat rw,relatime,fmask=0022,dmask=0022,\
  codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro 0 0

Obviously iocharset=ascii is sub-optimal. When I re-mount with the option iocharset=utf8 it correctly represents the correct iocharset value:

$ grep vfat /proc/mounts
/dev/loop0 /tmp/tmp.Migr78uZ75 vfat rw,relatime,fmask=0022,dmask=0022,\
  codepage=437,iocharset=utf8,shortname=mixed,errors=remount-ro 0 0

Example:

$ cp 测试.pdf /tmp/tmp.Migr78uZ75/
cp: cannot create regular file '/tmp/tmp.Migr78uZ75/测试.pdf': Invalid argument
$ sudo mount -o loop,iocharset=utf8  ~/vfat.img /tmp/tmp.Migr78uZ75/
$ cp 测试.pdf /tmp/tmp.Migr78uZ75/
$ echo $?
0
$ ls -li /tmp/tmp.Migr78uZ75/
total 0
167 -rwxr-xr-x. 1 root root 0 Sep 25 21:57 测试.pdf

Next, the situation of having problems moving files happens more often than you think. Depending on the exact details of the situation, I've used variations on a number of the answers cited here.

To summarize these a bit:

Option 1: Move the file by reference.

The file is stored on an ext* filesystem by it's "inode" number. You can verify/see this number by adding the -i flag to ls:

$ ls -i
3312906 测试.pdf

From here, it's possible to reference the file by it's inode number with the find command and then execute a mv command indirectly:

$ find * -inum 3312906  -exec mv "{}"  /tmp/tmp.Migr78uZ75/  \;

Option 2: Odd escaping

Both find and xargs have the ability to use NUL (\0) characters for field separation, allowing for working around crazy characters:

$ find . -inum 3312906 -print0 | xargs -0 -I '{}' mv '{}' /tmp/tmp.Migr78uZ75/
  • The option iocharset=utf8 solved the problem. This is exhaustive, great answer. Thank you! – Kepler Sep 26 '18 at 5:53

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.