Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在bash中交换两个文件的最短方法_Linux_Bash_Command Line - Fatal编程技术网

Linux 在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 &&

可以在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 && 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"