如何在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()函数以原子方式交换path1path2引用的文件的内容。也就是说,所有并发进程都将看到预交换状态或后交换状态;他们永远不会看到处于不一致状态的文件。

然而,它只能在一些特别支持它的文件系统(如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

回到顶部