![同步不同格式的卷时处理保留字符](https://linux22.com/image/1612969/%E5%90%8C%E6%AD%A5%E4%B8%8D%E5%90%8C%E6%A0%BC%E5%BC%8F%E7%9A%84%E5%8D%B7%E6%97%B6%E5%A4%84%E7%90%86%E4%BF%9D%E7%95%99%E5%AD%97%E7%AC%A6.png)
我有一个 NAS,我想将其上的一些目录复制到 exfat 格式的外部 HDD 上。
问题是路径/文件名可能包含 exfat 的保留字符(请参阅https://en.wikipedia.org/wiki/Filename#Comparison_of_filename_limitations),(但它们是 UTF-8 编码的)例如:
/home/fricadelle/mount_point/my_mp3s/Jake "the snake" O'Brian/03 - is it music ?.mp3
这里“和?”是个问题。直接将此文件夹或文件名 cp -r 到我的硬盘会导致cannot create regular file
错误No such file or directory
。
我还没有找到令人满意的解决方案。这如何批量重命名无效编码的文件或批量替换无效编码字符?建议批量重命名所有内容。我不喜欢这样,因为这些文件在我的 ubuntu 桌面或 mac 或我的网络音频播放器上播放正常。我想将这些字符保留在我的 NAS 中。我想我还必须先将其复制到我的桌面上,然后批量重命名,然后将其复制到我的外部硬盘上。
理想情况下,我希望将某个选项传递给类似 rsync 的程序,以便将所有禁用字符即时映射到空格。这样文件名/文件夹名称只会在我的外部硬盘上更改。
答案1
我必须为我的音乐播放器同步脚本解决这个问题,因为现在是 2020 年,FAT(和 NTFS)仍然无法处理问号或冒号。
我选择用 __(双下划线)替换任何 ? 或 : 的实例,因为这可能永远不会产生问题。您可以使用其他类似的解决方案,并且可以扩展可替换字符列表以满足您的需求。
function func_PMP_naughtyFilesystem() {
# if the PMP uses FAT or NTFS then sub certain characters with __
printf '%s\n' "Some file systems are unable to handle certain characters. "
printf '%s\n' "FAT and NTFS file systems in particular are bad about this. "
printf '%s\n' "If you would like we can change : and ? into __ to avoid sync failures. "
read -rep "Is your PMP formatted to use one of these lesser file systems? (Y/n) " -n1 naughtyFilesystem
printf '\n'
}
function func_CreateSourceAndDestination() {
#
for (( i = 0 ; i < ${#files_syncSource[@]} ; i++ )) ; do
files_syncDestination[${i}]="${files_syncSource[${i}]#${directory_MusicLibraryRoot_source}}"
# printf '%s\n' "${files_syncDestination[${i}]}" # useful in debugging
if [ "${naughtyFilesystem}" != "n" ] ; then
files_syncDestination[${i}]="${files_syncDestination[${i}]//\:/__}"
files_syncDestination[${i}]="${files_syncDestination[${i}]//\?/__}"
fi
file_destinationPath="$( dirname -- "${directory_PMPRoot_destination}${files_syncDestination[${i}]}" )"
if [ ! -d "${file_destinationPath}" ] ; then
mkdir -p "${file_destinationPath}"
fi
# try process substitution
# rsync --files-from=<( printf "%s\n" "${files[@]}" ) source destination
# rsync -rltDvPm --files-from=<( printf "%s\n" "${files_syncSource[${i}]}" ) "${files_syncDestination[${i}]}"
# the above needs to lose the interation and destination should just be PMProot I guess
rsync -rltDvPmz "${files_syncSource[${i}]}" "${directory_PMPRoot_destination}${files_syncDestination[${i}]}"
done
}
首先,我询问用户是否要进行替换,然后,除非他们回答“不”,否则我会在每次同步之前进行这些替换。
如果您有任何疑问,请告诉我。