如果文件是目录,则不要移动它 mv bash

如果文件是目录,则不要移动它 mv bash

我正在编写一个脚本来帮助我整理文件。本质上,我希望脚本根据文件的扩展名来组织我的文件。当前的解决方案查看给定目录中的所有内容。这是一个问题,因为名称中带有点的文件夹会被移动。

我想知道是否有一个if statement可以用来检查该目录是否是实际目录的方法。如果它确实是一个目录,那么脚本不应移动它。

这是代码部分。我正在使用 afor loop来迭代文件,这大致基于我在 Windows 中的旧批处理脚本,因此这可能不是最好的方法。如果有更好的解决方案请告诉我:

#!/bin/bash
for i in *.*; do
  filename=$(basename -- "$i")
  extension="${filename##*.}"
  extension="$extension"files
  mkdir -p "$extension"
  mv "$i" "$extension"
done

答案1

我个人会使用 afind和 a循环,因为您可以分别使用 for 目录/文件while指定文件类型-type d/f

作为目录中的“一行”,您将从中运行它:

find . -maxdepth 1 -type f -name "*.*" | while IFS="" read -r line; do filename=$(basename -- "$line"); extension="${filename##.}.files"; mkdir -p "$extension"; mv "$line" "$extension"; done

或者在脚本中:

#!/bin/bash
find . -maxdepth 1 -type f -name "*.*" |
while IFS="" read -r line; do
    filename=$(basename -- "$line")
    extension="${filename##.}.files"
    mkdir -p "$extension"
    mv "$line" "$extension"
done

解释

find .- 从当前目录中查找文件和目录

-maxdepth 1- 只检查当前目录(2也会检查下一级目录)

-type f- 只匹配文件

-name *.*- 任何带有“.”的文件在名字里

我还将扩展名更改为.files一个变量声明,因为我认为这就是您想要的。如果您想说tmp.txt位于一个名为的目录中tmp.txtfiles(就像当前在您的脚本中一样),那么只需删除“。”像这样:

extension="${filename##.}files"

编辑:

因此,正如 @Kusalananda 指出的那样,循环 afind可能是一个坏主意。话虽如此,您仍然可以使用find此功能,只需使用临时文件来循环即可:

#!/bin/bash
find . -maxdepth 1 -type f -name "*.*" > myTemporaryFile

IFS=$'\n' # in case any filenames have spaces in them

for line in $(cat myTemporaryFile); do
    filename=$(basename -- "$line")
    extension="${filename##.}.files"
    mkdir -p "$extension"
    mv "$line" "$extension"
done

rm myTemporaryFile

答案2

我将提出另外两种方法;一个来自 Kusalananda 的评论,另一个完全来自另一个 shell。

首先,bash(和其他 shell)有一个简单的test运算符来查看某物是否是目录:[ -d something ];你可以这样使用它:

#!/bin/bash
for i in *.*; do
  [ -d "$i" ] && continue
  # ... rest of the script
done

上面的代码将检查*.*通配符中的每个“文件”,看看它是否是一个目录;如果是,则测试通过并且循环继续执行下一项(如果有)。

或者,您可以使用 zsh,它具有广泛的通配符功能,其中之一是将匹配限制为某些类型的文件(常规文件、目录等)。你可以这样使用它:

#!/bin/zsh
for i in *.*(.)
do
  # ... rest of your script
done

的特殊语法(.)“全局限定符”;括号表明它是一个限定符,句点表示我们正在寻找纯文件。结果是for循环将仅匹配文件,而不会匹配目录。

答案3

您可以-fif语句中使用来检查它是否是一个文件:

if [ -f "${i}" ];then
  echo "${i} is a file."
else
  echo "${i} is not a file."
fi

-d可用于判断是否是目录,并且!可以添加前缀来反转逻辑,即检查变量是否不是文件:

if [ ! -f "${i}" ];then
  echo "${i} is not a file"
fi

相关内容