逐行读取文件,然后处理为其他变量

时间:2019-06-18 10:38:24

标签: bash

我创建了一个文本文件,其中包含文件名列表,如下所示

022694-39.tar
022694-39.tar.2017-05-30_13:56:33.OLD
022694-39.tar.2017-07-04_09:22:04.OLD
022739-06.tar
022867-28.tar
022867-28.tar.2018-07-18_11:59:19.OLD
022932-33.tar

我试图逐行读取文件,然后使用awk在 .tar 之后删除任何内容,并使用它来创建文件夹(除非存在)。

然后计划将原始文件复制到具有$ LINE中存储的原始全名的新文件夹中。

$QNAP= "Path to storage"
$LOG_DIR/$NOVA_TAR_LIST= "Path to text file containing file names"
while read -r LINE; do
    CURNT_JOB_STRIPED="$LINE | `awk -F ".tar" '{print $1}'`"
    if [ ! -d "$QNAP/$CURNT_JOB_STRIPED" ]
        then
        echo "Folder $QNAP/$CURNT_JOB_STRIPED doesn't exist."
        #mkdir "$QNAP/$CURNT_JOB_STRIPED"
    fi
done <"$LOG_DIR/$NOVA_TAR_LIST"

不幸的是,这似乎是在尝试创建目录时尝试将所有文​​件名连接在一起,而不是一个一个地做,而我得到一个 File name too long

输出:

......951267-21\n951267-21\n961075-07\n961148-13\n961520-20\n971333-21\n981325-22\n981325-22\n981743-40\n999111-99\n999999-04g\n999999-44': File name too long

很抱歉,这很简单,有点菜鸟...

2 个答案:

答案 0 :(得分:1)

尝试如下修改脚本:

CURNT_JOB_STRIPED=$(echo "${LINE}" | awk -F ".tar" '{print $1}')

您必须使用$(...)进行命令替换。另外,应该打印变量LINE,以防止外壳程序将其值解释为命令,而是将其传递给管道的下一个命令(作为输入)。最后,您应该从awk表达式中删除反引号(这是命令替换的不建议使用的语法),因为您想要的是管道命令的结果。

有关更多信息,请查看http://tldp.org/LDP/abs/html/commandsub.html

或者,可读性差得多(两者都没有更高的性能,因此也只是出于“好奇心”),您可以使用而不是整个while循环:

xargs -I{} bash -c 'mkdir -p "${2}/${1%.tar*}"' - '{}' "${QNAP}" < "${LOG_DIR}/${NOVA_TAR_LIST}"

答案 1 :(得分:1)

问题出在CURNT_JOB_STRIPED="$LINE | `awk -F ".tar" '{print $1}'`"行。

`command`是旧式语法,应改为使用$(command)

$LINE变量应打印出来,以便awk可以通过管道接收其值。

如果您在子外壳程序($(command)中运行整个程序,则可以将输出分配给变量:var=$(date)

将变量放入${}是比较安全的,因此,如果周围有文本,则不会得到意外的结果。

这应该起作用: CURNT_JOB_STRIPED=$(echo "${LINE}" | awk -F '.tar' '{print $1}')


使用变量替换可以通过更高效的代码来实现,而且我相信阅读起来也很干净。

变量替换不会更改${LINE}变量,因此以后可以将其用作具有完整文件名的变量,而${LINE%.tar*}从变量值中剪切最后一个.tar文本,然后然后*开始。

while read -r LINE; do
        if [ ! -d "${QNAP}/${LINE%.tar*}" ]
        then
                echo "Folder ${QNAP}/${LINE%.tar*} doesn't exist."
                #mkdir "${QNAP}/${LINE%.tar*}"
        fi
done <"${LOG_DIR}/${NOVA_TAR_LIST}"

这样,您就不会将目录名存储为变量,而${LINE}仅存储文件名。如果您需要将其放入变量中,则可以轻松完成此操作:var="${LINE%.tar*}"


变量替换:

还有更多我只选择了这4个,因为它们在这里相似且相关。

$ {var#pattern}-从左侧删除与模式匹配的文本后使用var的值

$ {var ## pattern}-与上面相同,但是删除了最长的匹配项,而不是最短的

$ {var%pattern}-从右侧删除匹配模式的文本后使用var的值

$ {var %% pattern}-与上面相同,但删除了最长的匹配项而不是最短的