使用 If,then...fi 命令如何判断用户输入的文件格式是否正确?

使用 If,then...fi 命令如何判断用户输入的文件格式是否正确?

我正在尝试创建一个非常基本的 bash 脚本,告诉用户在继续之前是否输入了正确的脚本文件格式。例如:

echo "Input .txt file here:"
read file
if $file = *.txt
    then 
    echo "File is in correct format."
    else
    echo "File is not in correct format. Please recheck your file."
    fi

可以用什么来做到这一点?

命令(如下)不起作用,只是报告“其他”,而不是做我真正想做的事情。

$file = *.txt

答案1

当然,仅仅文件扩展名并不是文件格式。这只是任何人都可以通过简单的操作来更改的文本:

mv image.png word.txt

话虽这么说,在这种情况下,您可以简单地使用以下basename命令:

base=`basename "$file" .txt`
if test "$base" != "$file"
then
    echo "Success!"
else
    echo "Wrong extension..."
fi

答案2

您可以尝试以下脚本:

if [ ".$(echo "$file"| cut -d. -f2)" == ".txt" ]
then
echo "File is in correct format."
else
echo "File is not in correct format. Please recheck your file."
fi

.如果您的文件名有多个(点),您可以使用以下命令

if [ ".$(echo "$file"| awk -F. '{print $NF}')" == ".txt" ]

答案3

好吧,让我们回顾一下您要做什么。首先要意识到的是,你不想检查文件名是否为“ *.txt”,你想看看它是否是与模式匹配*.txt“。此外,您还会在 Unix 脚本编写中遇到多种不同类型的模式;最常见的是通配符(或“glob”)模式和正则表达式(正则表达式语法有许多版本)。这里有一个全局模式。

因此,您需要一个进行全局模式匹配的工具。 (好吧,您也可以用不同的语法重写模式,或者采用完全不同的方法来检查扩展;但我们暂时坚持使用 glob 模式匹配。)

其次,您在声明中使用它if。语句中的条件(和if之间的东西)是ifthen命令(或者至少是类似命令的东西)。该if语句取决于该命令是成功还是失败。if语句中最常用的命令之一是[,它是一个命令,如下所示:

if [ "$file" = "*.txt" ]; then

看起来[像是某种 shell 语法或奇怪的括号,但事实并非如此,它只是一个常规命令(大部分相当于该test命令)。但它是一个常规命令,要求其最后一个参数为“ ]”(同样,不是真正的右括号,只是常规命令参数),并将其其余参数解析为逻辑表达式。请man [参阅 其语法。另外,请注意,我对"$file"和都加了双引号,"*.txt"因为(作为普通命令参数)文件名将受到分词的影响,并且它们都将受到通配符扩展的影响,这可能会对表达式语法造成严重破坏。

[不进行模式匹配。它可以进行字符串和数字(​​整数)比较,但不能进行模式匹配。所以我们需要寻找其他地方。

如果您使用 bash(或 zsh 甚至 ksh,但是不是dash 或其他一些更基本的 shell),您可以使用[[ ]].不同于[shell 语法而不是常规命令,它本质上是[.还有它=与运算符进行模式匹配如果您将右侧不加引号。也就是说,这将进行文字字符串比较:

if [[ "$file" = "*.txt" ]]; then

这将进行全局模式修补:

if [[ "$file" = *.txt ]]; then

(请注意,实际上您不需要$file对其中任何一个进行双引号,但我更喜欢自动对变量引用进行双引号,因为双引号它们几乎总是安全的,而将它们不加引号通常是不安全的,并且与需要引用的异常相比,更容易记住需要不引用的异常。)

所以,最后一个命令是你可能的答案假如您正在使用支持的 shell [[ ]](即,如果您使用的是 bash shebang#!/bin/bash#!/usr/bin/env bash,而不是通用的 sh )。

如果您使用 plain sh,那么我们必须稍微更改一下规则。在通用 POSIX shell 中进行通配符模式匹配的最简单方法是case使用if.这很好,因为通配符模式匹配就是case生来要做的:

case "$file" in
    *.txt )
        echo "File is in correct format." ;;

    * )
        "File is not in correct format. Please recheck your file." ;;
esac

请注意,模式*(匹配与早期模式不匹配的任何内容)的功能类似于语句else中的子句if。此外,语法需要一些时间来适应,在)每个模式和匹配的命令之间以及;;在每个模式命令的末尾。

如果我们从“我想匹配 glob 模式”切换到“我想查看文件名是否以 '.txt' 结尾”,还有其他选项。有几种(POSIX 标准)方法可以通过在文件名变量扩展上使用修饰符来实现此目的。例如,将从变量值的末尾${var%pattern}删除匹配项(pattern如果它匹配)。因此,一个标准技巧是尝试从文件名末尾删除“.txt”,然后查看它是否发生变化。如果是,则“.txt”匹配;如果没有,那就没有。像这样:

if [ "$file" != "${file%.txt}" ]; then

请注意,这使用了不等于测试 ( !=),因为只有成功从末尾删除“.txt”,字符串才会不同。

您也可以删除最后一个“.”。在文件名中${file##*.}(看看剩下的是否是“txt”),但这有一个问题,它会认为文件名“txt”匹配。哎呀。

相关内容