在 bash 中使用 if 条件语句移动所有文件时跳过“特定文件扩展名文件”

在 bash 中使用 if 条件语句移动所有文件时跳过“特定文件扩展名文件”

我正在写一个bash脚本这会将文件/目录从现有目录路径移动到另一个目录路径。但在使用for loopwithif condition语句时我无法跳过一些扩展文件。我的脚本运行时没有错误,但它不会跳过我在其中指定的所需扩展文件,if condition而是移动所有文件和目录。下面是我尝试为其创建的脚本。

请指导我哪里做错了。

以下是我正在尝试做的事情。

#!/bin/env bash

#moving home profile data to another location
echo "Moving Desktop Files"
path=/home/$USER/Desktop/*
for m in $path
do
      link=$(basename -s .lnk ${m})
      desktop=$(basename -s .desktop ${m})
      if [[  "${link}.lnk" == "${m}" ]] || [[ "${desktop}.desktop" == "${m}" ]]
      then
                echo "skipping link and desktop extension files"
                continue
      fi
mv -n "$m"  /home/$USER/CoreData/HOME/Desktop/

done

答案1

您以一种非常迂回的方式匹配文件名后缀,并且您编写循环的方式使其无法处理名称中带有空格的文件。

与您的语句相关的主要问题if$m是 路径名,包含目录路径元素,而$desktop$link,如果解释为文件名,则没有目录路径元素。

更安全代码的建议:

#!/bin/bash

for name in "$HOME/Desktop"/*; do
    if [[ $name == *.lnk ]] || [[ $name == *.desktop ]]; then
        printf 'Skipping "%s"\n' "$name"
    else
        mv -n -- "$name" "$HOME/CoreData/HOME/Desktop"
    fi
done

这使用与in==内的(通配)模式匹配。[[ ... ]]bash

如果您确实想单独进行名称通配并将它们保存在变量中,请使用数组:

names=( "$HOME/Desktop"/* )

for name in "${names[@]}"; do ... done

请注意,上面的引用对于保持各个路径名的完整性很重要。

或者,使用以下case ... esac语句/bin/sh

#!/bin/sh

for name in "$HOME/Desktop"/*; do
    case $name in
        *.lnk|*.desktop)
            printf 'Skipping "%s"\n' "$name"
            ;;
        *)
            mv -n -- "$name" "$HOME/CoreData/HOME/Desktop"
    esac
done

同样,您想单独进行通配符吗:

set -- "$HOME/Desktop"/*

for name do ... done

这使用位置参数而不是命名数组。 shellsh不支持命名数组。

或者,使用rsync

rsync --archive --verbose \
    --exclude='*.lnk' \
    --exclude='*.desktop' \
    "$HOME/Desktop/" "$HOME/CoreData/HOME/Desktop"

(然后"$HOME/Desktop"根据需要删除)

相关内容