Linux 在bash中交换两个文件的最短方法
可以在bash中交换两个文件吗 或者,它们可以用比这更短的方式交换:Linux 在bash中交换两个文件的最短方法,linux,bash,command-line,Linux,Bash,Command Line,可以在bash中交换两个文件吗 或者,它们可以用比这更短的方式交换: cp old tmp cp curr old cp tmp curr rm tmp 肯定是mv而不是cp $ mv old tmp && mv curr old && mv tmp curr 效率稍微高一点 包装到可重用的外壳函数中: function swap() { local TMPFILE=tmp.$$ mv "$1" $TMPFILE &&
cp old tmp
cp curr old
cp tmp curr
rm tmp
肯定是
mv
而不是cp
$ mv old tmp && mv curr old && mv tmp curr
效率稍微高一点
包装到可重用的外壳函数中:
function swap()
{
local TMPFILE=tmp.$$
mv "$1" $TMPFILE && mv "$2" "$1" && mv $TMPFILE "$2"
}
你可以简单地移动它们,而不是复制
#!/bin/sh
# Created by Wojtek Jamrozy (www.wojtekrj.net)
mv $1 cop_$1
mv $2 $1
mv cop_$1 $2
使用mv意味着您只需执行一次操作,无需最终rm,而且mv只更改目录项,因此您不会使用额外的磁盘空间进行复制
然后尝试在shell函数swap()或类似的函数上实现。如果您确实这样做了,请非常小心地检查错误代码。可能具有可怕的破坏性。还需要检查预先存在的tmp文件 将此添加到您的.bashrc中:
tmpfile=$(mktemp $(dirname "$file1")/XXXXXX)
mv "$file1" "$tmpfile"
mv "$file2" "$file1"
mv "$tmpfile" "$file2"
function swap()
{
local TMPFILE=tmp.$$
mv "$1" $TMPFILE
mv "$2" "$1"
mv $TMPFILE "$2"
}
如果要处理中间mv
操作的潜在故障,请选中
请注意,这两个答案都没有提供原子解决方案,因为使用Linux系统调用和/或流行的Linux文件系统不可能实现这样的解决方案。对于Darwin内核,请检查exchangedatasyscall。是否确实要交换它们? 我认为值得一提的是,您可以使用mv自动备份被覆盖的文件:
mv new old -b
您将获得:
old and old~
如果你愿意的话
old and old.old
您可以使用-S将~更改为自定义后缀
mv new old -b -S .old
ls
old old.old
使用这种方法,您实际上可以更快地交换它们,只需2 mv:
mv new old -b && mv old~ new
结合最佳答案,我将其放入我的~/.bashrc中:
function swap()
{
tmpfile=$(mktemp $(dirname "$1")/XXXXXX)
mv "$1" "$tmpfile" && mv "$2" "$1" && mv "$tmpfile" "$2"
}
哈代的主意对我来说已经足够好了。 所以我尝试了以下两个文件来交换“sendsms.properties”、“sendsms.properties.swap”。 但一旦我调用这个函数作为同一个参数“sendsms.properties”,这个文件就被删除了。为了避免这种失败,我给自己加了几行:-)
再次感谢哈代;-) 使用此处提供的任何解决方案时,我都遇到了一个问题:您的文件名将被切换 我使用了
basename
和dirname
来保持文件名的完整性*
swap() {
if (( $# == 2 )); then
mv "$1" /tmp/
mv "$2" "`dirname $1`"
mv "/tmp/`basename $1`" "`dirname $2`"
else
echo "Usage: swap <file1> <file2>"
return 1
fi
}
其他解决方案的最终结果是:
dir1/file2: this is file1
dir2/file1: this is file2
内容已交换,但文件名保留。我的解决方案是:
dir1/file1: this is file1
dir2/file2: this is file2
内容和名称被交换。一个稍微强化的版本,可用于文件和目录:
function swap()
{
if [ ! -z "$2" ] && [ -e "$1" ] && [ -e "$2" ] && ! [ "$1" -ef "$2" ] && (([ -f "$1" ] && [ -f "$2" ]) || ([ -d "$1" ] && [ -d "$2" ])) ; then
tmp=$(mktemp -d $(dirname "$1")/XXXXXX)
mv "$1" "$tmp" && mv "$2" "$1" && mv "$tmp"/"$1" "$2"
rmdir "$tmp"
else
echo "Usage: swap file1 file2 or swap dir1 dir2"
fi
}
这在Linux上工作。关于OS X不太清楚。我在一个工作脚本中提供了这个。它是作为函数编写的,但是您可以调用它
d_swap lfile rfile
GNU mv具有-b和-T开关。您可以使用-T来处理目录
开关
引号用于带空格的文件名
这有点冗长,但我已经在文件和目录中使用过很多次了。在某些情况下,您可能希望使用目录的名称重命名文件,但此函数无法处理此问题
如果您只想重命名文件(让它们留在原来的位置),那么这不是很有效,最好使用shell变量
d_swap() {
test $# -eq 2 || return 2
test -e "$1" || return 3
test -e "$2" || return 3
if [ -f "$1" -a -f "$2" ]
then
mv -b "$1" "$2" && mv "$2"~ "$1"
return 0
fi
if [ -d "$1" -a -d "$2" ]
then
mv -T -b "$1" "$2" && mv -T "$2"~ "$1"
return 0
fi
return 4
}
此函数将重命名文件。它使用一个临时名称(在名称前加一个点“.”),以防文件/目录位于同一目录中,通常情况下就是这样
d_swapnames() {
test $# -eq 2 || return 2
test -e "$1" || return 3
test -e "$2" || return 3
local lname="$(basename "$1")"
local rname="$(basename "$2")"
( cd "$(dirname "$1")" && mv -T "$lname" ".${rname}" ) && \
( cd "$(dirname "$2")" && mv -T "$rname" "$lname" ) && \
( cd "$(dirname "$1")" && mv -T ".${rname}" "$rname" )
}
这要快得多(没有复制,只是重命名)。它甚至更丑陋。它将重命名任何内容:文件、目录、管道、设备。这是我在系统上用作命令的内容(
$HOME/bin/swapfiles
)。我认为它对坏的东西是相对有弹性的
#!/bin/bash
if [ "$#" -ne 2 ]; then
me=`basename $0`
echo "Syntax: $me <FILE 1> <FILE 2>"
exit -1
fi
if [ ! -f $1 ]; then
echo "File '$1' does not exist!"
fi
if [ ! -f $2 ]; then
echo "File '$2' does not exist!"
fi
if [[ ! -f $1 || ! -f $2 ]]; then
exit -1
fi
tmpfile=$(mktemp $(dirname "$1")/XXXXXX)
if [ ! -f $tmpfile ]; then
echo "Could not create temporary intermediate file!"
exit -1
fi
# move files taking into account if mv fails
mv "$1" "$tmpfile" && mv "$2" "$1" && mv "$tmpfile" "$2"
#/bin/bash
如果[“$#”-ne 2];然后
me=`basename$0`
echo“语法:$me”
出口-1
fi
如果[!-f$1];然后
echo“文件“$1”不存在!”
fi
如果[!-f$2];然后
echo“文件“$2”不存在!”
fi
如果[!-f$1 |!-f$2]];然后
出口-1
fi
tmpfile=$(mktemp$(dirname“$1”)/XXXXXX)
如果[!-f$tmpfile];然后
echo“无法创建临时中间文件!”
出口-1
fi
#如果mv失败,移动文件时应考虑
mv“$1”$tmpfile”和mv“$2”$1”和mv“$tmpfile”$2”
这里有一个交换
脚本,带有偏执错误检查,以避免不太可能出现的故障
- 如果任何操作失败,都会报告
- 第一个参数的路径用于临时路径(以避免在文件系统之间移动)
- 在不太可能的情况下,第二步失败,第一步恢复
#/垃圾箱/垃圾箱
如果[-z“$1”]| |[-z”$2”];然后
echo“需要2个文件参数,中止!”
出口1
fi
如果[!-z“$3”];然后
echo“预期有2个文件参数,但发现第3个,中止!”
出口1
fi
如果[!-f“$1”];然后
echo“未找到文件“$1”,中止!”
出口1
fi
如果[!-f“$2”];然后
echo“未找到文件“$2”,中止!”
出口1
fi
#避免在驱动器之间移动
tmp=$(mktemp--tmpdir=“$(dirname'$1')”)
如果[$?-ne 0];然后
echo“创建临时文件失败,中止!”
出口1
fi
#错误时退出,
mv“$1”$tmp”
如果[$?-ne 0];然后
echo“无法访问第一个文件“$1”,中止!”
rm“$tmp”
出口1
fi
mv“$2”“$1”
如果[$?-ne 0];然后
echo“无法移动第一个文件“$2”,中止!”
#恢复状态
mv“$tmp”$1
如果[$?-ne 0];然后
echo“无法移动文件:(无法还原)“$1”已保留在“$tmp”!”
fi
出口1
fi
mv“$tmp”$2
如果[$?-ne 0];然后
#这不太可能!
echo“无法移动文件:(无法还原)“$1”已保留在“$tmp”处,“$2”作为“$1”!”
出口1
fi
…如果tmp
出现问题,则不会将您的文件放入涅磐+1设置tmpfile=/tmp/tmp.$$
是否更好?如果mv“$2”“$1”失败,您如何检测并回滚?Michael:如果您对此感到担忧,那么您可以选择。您可以在操作中打印临时文件的名称,以便自己将其复制回去。或者您甚至可以在目录中创建两者的.backup文件。您可以选择。如果要在与源文件相同的目录中创建临时文件,则可以使用ln
而不是mv
。
d_swap() {
test $# -eq 2 || return 2
test -e "$1" || return 3
test -e "$2" || return 3
if [ -f "$1" -a -f "$2" ]
then
mv -b "$1" "$2" && mv "$2"~ "$1"
return 0
fi
if [ -d "$1" -a -d "$2" ]
then
mv -T -b "$1" "$2" && mv -T "$2"~ "$1"
return 0
fi
return 4
}
d_swapnames() {
test $# -eq 2 || return 2
test -e "$1" || return 3
test -e "$2" || return 3
local lname="$(basename "$1")"
local rname="$(basename "$2")"
( cd "$(dirname "$1")" && mv -T "$lname" ".${rname}" ) && \
( cd "$(dirname "$2")" && mv -T "$rname" "$lname" ) && \
( cd "$(dirname "$1")" && mv -T ".${rname}" "$rname" )
}
#!/bin/bash
if [ "$#" -ne 2 ]; then
me=`basename $0`
echo "Syntax: $me <FILE 1> <FILE 2>"
exit -1
fi
if [ ! -f $1 ]; then
echo "File '$1' does not exist!"
fi
if [ ! -f $2 ]; then
echo "File '$2' does not exist!"
fi
if [[ ! -f $1 || ! -f $2 ]]; then
exit -1
fi
tmpfile=$(mktemp $(dirname "$1")/XXXXXX)
if [ ! -f $tmpfile ]; then
echo "Could not create temporary intermediate file!"
exit -1
fi
# move files taking into account if mv fails
mv "$1" "$tmpfile" && mv "$2" "$1" && mv "$tmpfile" "$2"