Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.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
为什么bash中的mv命令会删除文件?_Bash - Fatal编程技术网

为什么bash中的mv命令会删除文件?

为什么bash中的mv命令会删除文件?,bash,Bash,运行以下脚本重命名当前文件夹中的所有.jpg文件有时效果良好,但它通常会删除一个或多个正在重命名的文件。如何编写脚本来重命名文件而不在过程中删除它们?这是在MacOSX10.8上运行的,使用的是GNUBash版本3.2.48 这是一个示例文件列表,我将对其进行更改以进行说明: 原始文件 red.jpg blue.jpg green.jpg 如果计数器设置为5,则重命名文件 file_5.jpg file_6.jpg file_7.jpg 相反,我通常会丢失一个或多个文件 #!/bin/bas

运行以下脚本重命名当前文件夹中的所有.jpg文件有时效果良好,但它通常会删除一个或多个正在重命名的文件。如何编写脚本来重命名文件而不在过程中删除它们?这是在MacOSX10.8上运行的,使用的是GNUBash版本3.2.48

这是一个示例文件列表,我将对其进行更改以进行说明:

原始文件

red.jpg
blue.jpg
green.jpg
如果计数器设置为5,则重命名文件

file_5.jpg
file_6.jpg
file_7.jpg
相反,我通常会丢失一个或多个文件

#!/bin/bash  

counter=5

for file in *.jpg; do

    echo renaming "$file" to "file_${counter}.jpg";
    mv "$file" "file_${counter}.jpg";
    let "counter+=1";

done
**更新** 它似乎不再删除文件,但输出仍不符合预期。例如:

file_3.jpg
file_4.jpg
变成

file_3.jpg
file_5.jpg
当计数器设置为4时,当预期输出为

file_4.jpg
file_5.jpg
-


问题是有些文件已经有了与目标名称对应的名称。例如,如果存在文件

file_1.jpg
file_7.jpg
counter=7
开始,第一步用
file\u 1.jpg
覆盖
file\u 7.jpg
,然后将其重命名为
file\u 8.jpg

您可以使用
mv-n
来防止碰撞(如果支持),或者在运行命令之前测试是否存在碰撞

if [[ -e file_${counter}.jpg ]] ; then
    echo Skipping "$file", file exists.
else
    mv "$file" "file_${counter}.jpg"
fi

问题是有些文件已经有了与目标名称对应的名称。例如,如果存在文件

file_1.jpg
file_7.jpg
counter=7
开始,第一步用
file\u 1.jpg
覆盖
file\u 7.jpg
,然后将其重命名为
file\u 8.jpg

您可以使用
mv-n
来防止碰撞(如果支持),或者在运行命令之前测试是否存在碰撞

if [[ -e file_${counter}.jpg ]] ; then
    echo Skipping "$file", file exists.
else
    mv "$file" "file_${counter}.jpg"
fi

乔罗巴所说的是正确的。您还可以使用:

mv "$file" "file_${counter}.jpg" -n
在目标文件名已存在时忽略移动,或

mv "$file" "file_${counter}.jpg" -i

询问它是否应该覆盖。

乔洛巴所说的是正确的。您还可以使用:

mv "$file" "file_${counter}.jpg" -n
在目标文件名已存在时忽略移动,或

mv "$file" "file_${counter}.jpg" -i

要询问它是否应该覆盖。

而不是迭代
*.jpg
您应该跳过已重命名的文件,即
文件.[0-9]*.jpg
,并按如下方式运行循环:

counter=5

while read file; do
   echo renaming "$file" to "file_${counter}.jpg";
   mv -n "$file" "file_${counter}.jpg";
   let "counter+=1";
done < <(find . -maxdepth 1 -name "*.jpg" -not -name "file_[0-9]*.jpg")
计数器=5
读取文件时;做
echo将“$file”重命名为“file_${counter}.jpg”;
mv-n“$file”“file_${counter}.jpg”;
设“计数器+=1”;

完成<而不是迭代
*.jpg
您应该跳过已重命名的文件,即
文件.[0-9]*.jpg
,并按如下方式运行循环:

counter=5

while read file; do
   echo renaming "$file" to "file_${counter}.jpg";
   mv -n "$file" "file_${counter}.jpg";
   let "counter+=1";
done < <(find . -maxdepth 1 -name "*.jpg" -not -name "file_[0-9]*.jpg")
计数器=5
读取文件时;做
echo将“$file”重命名为“file_${counter}.jpg”;
mv-n“$file”“file_${counter}.jpg”;
设“计数器+=1”;

完成<我想你对地球仪的一个明显问题感到困惑。如果glob匹配file_2.jpg,它将尝试创建file_file_2.jpg(我的意思不是字面意义上的,只是您将重新处理已经处理过的文件)。要解决此问题,需要确保初始glob表达式与已移动的文件不匹配:

shopt -s extglob

i=0
for f in !(file_*).jpg ; do
    while [[ -e "file_${i}.jpg" ]] ; do
        (( i++ ))
    done

    mv -v "$f" "file_$i.jpg"
    (( i++ ))
done

我认为你对地球仪的一个明显问题感到困惑。如果glob匹配file_2.jpg,它将尝试创建file_file_2.jpg(我的意思不是字面意义上的,只是您将重新处理已经处理过的文件)。要解决此问题,需要确保初始glob表达式与已移动的文件不匹配:

shopt -s extglob

i=0
for f in !(file_*).jpg ; do
    while [[ -e "file_${i}.jpg" ]] ; do
        (( i++ ))
    done

    mv -v "$f" "file_$i.jpg"
    (( i++ ))
done

另一种方法是继续计数,直到文件不存在:

#!/bin/bash  

counter=1
shopt -s extglob

for file in *.jpg; do
    [[ $file == ?(*/)file_+([[:digit:]]).jpg ]] && continue

    until
        newname=file_$(( counter++ )).jpg
        [[ ! -e $newname ]]
    do
        continue
    done

    echo "renaming $file to $newname.";

    mv -i "$file" "$newname" ## Remove the -i option if you think it's safe already.
done
递归地做事情时:

#!/bin/bash  

shopt -s  extglob    
counter=1

while read file; do
    dirprefix=${file%%+([^/])

    until
        newfile=$dirprefix/file_$(( counter++ )).jpg
        [[ ! -e $newfile ]]
    do
        continue
    done

    echo "renaming $file to $newfile."

    mv -i "$file" "$newfile" ## Remove the -i option if you think it's safe already.
done < <(find -type f -name '*.jpg' -and -not -regex '^.*/file_[0-9]\+$')
#/bin/bash
shopt-s extglob
计数器=1
读取文件时;做
dirprefix=${file%%+([^/])
直到
newfile=$dirprefix/file_$((计数器++).jpg
[!-e$newfile]]
做
持续
完成
echo“将$file重命名为$newfile”
mv-i“$file”“$newfile”##如果您认为-i选项已经安全,请删除它。

完成<另一种方法是继续计数,直到文件不存在:

#!/bin/bash  

counter=1
shopt -s extglob

for file in *.jpg; do
    [[ $file == ?(*/)file_+([[:digit:]]).jpg ]] && continue

    until
        newname=file_$(( counter++ )).jpg
        [[ ! -e $newname ]]
    do
        continue
    done

    echo "renaming $file to $newname.";

    mv -i "$file" "$newname" ## Remove the -i option if you think it's safe already.
done
递归地做事情时:

#!/bin/bash  

shopt -s  extglob    
counter=1

while read file; do
    dirprefix=${file%%+([^/])

    until
        newfile=$dirprefix/file_$(( counter++ )).jpg
        [[ ! -e $newfile ]]
    do
        continue
    done

    echo "renaming $file to $newfile."

    mv -i "$file" "$newfile" ## Remove the -i option if you think it's safe already.
done < <(find -type f -name '*.jpg' -and -not -regex '^.*/file_[0-9]\+$')
!/bin/bash
shopt-s extglob
计数器=1
在读取文件时;执行以下操作:
dirprefix=${file%%+([^/])
直到
newfile=$dirprefix/file_$((计数器++).jpg
[!-e$newfile]]
做
持续
完成
echo“将$file重命名为$newfile”
mv-i“$file”“$newfile”##如果您认为-i选项已经安全,请删除它。

done<您是说当给定一个数字时,三个“彩色”JPG文件中的一个丢失了-您有一个具有3个输入和(名义上)可复制的测试用例问题中引用的3个输出文件?或者它是否发生在表面上与颜色/数字示例类似的其他情况下?原始文件名的格式是否与修订后的文件名相同?我猜只有在某些文件已命名为file.*.jpgar的情况下才会发生。你是说三个“彩色”JPG文件中的一个是m当给定一个数字时,issing-您有一个具有3个输入的可复制测试用例,并且(名义上)3问题中引用的输出文件?或者在表面上类似于颜色/数字示例的其他情况下发生?原始文件名是否与修改后的文件名格式相同?我猜只有当某些文件已命名为file*.jpg时才会发生。这有助于不再删除文件,但仍然有“问题更新”中描述的某些情况下的意外重命名行为。@waspinator:然后创建一个临时目录,将所有文件移到新名称下,最后移回并删除目录。这有助于它不再删除文件,但在某些情况下仍有意外重命名行为,如所述。”“问题更新”中的“d”。@waspinator:然后创建一个临时目录,将所有文件移到新名称下,最后移回并删除目录。