如何在Unix中交换文件名?
任何方式快速做到这一点,而不使用临时变量?是否有内置函数?如何在Unix中交换文件名?
编辑:谢谢你们的答案。看起来我需要澄清我的问题,但大多数情况下你们都假设正确:有两个文件,文件名称是相反的。
- 文件具有名B-name.file
- 文件B具有名A-name.file
我想对文件被命名为A-name.file和文件B被命名为B-name.file。
我同意,情况不会经常发生,但它只是发生在我身上,我想快速修复。
回答:
OK,愚蠢的问题,但你为什么不能简单地这样做(在shell脚本):
mv $fileA $fileA.$$ mv $fileB $fileA
mv $fileA.$$ $fileB
和是的,当然它采用的是临时文件,但它更简洁,然后其他答案。
回答:
在shell脚本级别 - 没有标准命令,重命名至少包含一个临时文件名(注意不同文件系统上的文件!)。
在C代码级别,所有计算机上都没有标准函数来交换文件名 - 其中一个因素是处理不同文件系统上的文件的问题。
在一个单一的文件系统:
file1=one-file-name file2=tother-file
file3=tmp.$$
trap "" 1 2 3 13 15
ln $file1 $file3
rm $file1
ln $file2 $file1
rm $file2
ln $file3 $file2
rm $file3
trap 1 2 3 13 15
这不完全是傻瓜式的证明 - 但它是一个半体面的逼近,如果$ file1和$文件2是相同的文件系统上(和我”我们假设$ file3是同一文件系统上的一个名称)。固定它来处理所有的疣是...不平凡的。 (考虑$文件1 == $文件2,例如)
代码模拟相当多的系统调用,一个C程序将不得不作出 - ln
映射到link()
和rm
映射到unlink()
。如果你明白它不会做什么,那么较新的(如只有二十岁的)功能rename()
可能会被用来取得良好的效果。使用mv
命令而不是链接和删除意味着文件将在需要时在文件系统之间移动;这可能会有所帮助 - 或者这可能意味着您的磁盘空间在您无意使用时会填满。从部分错误中恢复并不是完全微不足道的。
回答:
也许可以用做:
file_B = fopen(path_b, 'r'); rename(path_a, path_b);
file_B_renamed = fopen(path_a, 'w');
/* Copy contents of file_B into file_B_renamed */
fclose(file_B_renamed);
fclose(file_B);
有可能是一个办法(我在寻找通过POSIX规范看到的,但我不会赌)创建一个从硬链接inode编号;这最终会做这样的事情
file_B = fopen(path_b, 'r'); rename(path_a, path_b);
make_hardlink(file_B, path_a);
回答:
“swap文件名”是什么意思?你是在谈论文件系统,还是只是在你的程序中的变量?
如果你的程序是C++,并且你有两个文件名在字符串中,并且想交换它们,请使用std :: swap。这不仅改变了程序中的变量:
std::string filenameA("somefilename"); std::string filenameB("othername");
std::swap(filenameA, filenameB);
std::cout << filenameA << std::endl; // prints "othername"
如果磁盘上有两个文件,和你想要的名称交换内容与对方的话没有,有没有办法来容易,如果你想保留硬链接。如果你只是想执行一个“安全保存”,那么unix rename()系统调用会在原子操作中将目标文件与源文件一起打开(原子操作可能由底层文件系统支持)。因此,你会安全保存这样的:
std::string savename(filename); savename += ".tmp";
... write data to savename ...
if (::rename(savename.c_str(), filename.c_str()) < 0) {
throw std::exception("oops!");
}
如果你真的,真的需要交换磁盘上的文件(比如说,保留的备份副本),然后输入硬链接。注意:所有文件系统(特别是某些SMB文件共享)都不支持硬链接,因此如果需要,您需要实施一些备份。您将需要一个临时文件名称,但不是任何临时数据存储。虽然你可以用link()和unlink()手动实现它(记住:UNIX中的文件可以有多个硬链接),但使用rename()会更容易。尽管如此,你无法完全原子地进行交换。
假设的oldfile是“filname.dat”和newfile中是“filename.dat.bak”你会得到这样的:
::link(oldfile, tempfile); ::rename(newfile, oldfile);
::rename(tempfile, newfile);
如果您链接之后崩溃,你就会有新的数据newfile和oldfile和tempfile中的旧数据。 如果第一重命名后崩溃,你必须在的oldfile在临时文件的新数据和旧数据(而不是NEWFILE!)
回答:
达尔文/ Mac OS X上有exchangedata()
系统调用:
exchangedata()
函数以原子方式交换path1和path2引用的文件的内容。也就是说,所有并发进程都将看到预交换状态或后交换状态;他们永远不会看到处于不一致状态的文件。
然而,它只能在一些特别支持它的文件系统(如Apple的HFS和HFS +)上实际工作,而且我在其他系统上没有看到任何类似的系统调用。可移植的方法是使用第三个临时文件名,并且该操作不会是原子操作。
回答:
这可以用小帮手完成,只需放入.bashrc,.zshrc或您的配置。
function swap() { mv $1 $1._tmp && mv $2 $1 && mv $1._tmp $2 }
而且使用它作为常规功能:
$ cat a b Alfa
Beta
$ swap a b && cat a b
Beta
Alfa
以上是 如何在Unix中交换文件名? 的全部内容, 来源链接: utcz.com/qa/259062.html