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

Kepler
  • 43

1 Answers1

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/