shell脚本中的连接和'basename'的使用

Pra*_*nav 1 bash shell sed

我想从特定目录中读取所有文件名,然后通过在另一个目录中向它们附加一些字符串来创建具有这些名称的新文件.

例如>'A','B','C'在'logs'目录中,然后脚本应在'tmp'目录中创建'A_tmp','B_tmp','C_tmp'

我正在使用的是 -

tempDir=./tmp/
logDir=./logs/

for file in $( find `echo $logDir` -type f )
 do
      name=eval basename $file
      echo $name
      name=$(echo $name | sed 's/.$//')
      echo $tempDir
      opFile=$tempDir$name
      echo $opFile
 done
Run Code Online (Sandbox Code Playgroud)

但我理解的是,$ file包含'\n'作为最后一个字符,我无法连接字符串.

现在我不是创建文件,只打印所有名称.

那么,我如何从文件名中删除'\n',我的理解是否正确?

Jon*_*ler 5

分析

您的脚本中有许多问题需要解决.让我们一步一步来:

tempDir=./tmp/
logDir=./logs/

for file in $( find `echo $logDir` -type f )
Run Code Online (Sandbox Code Playgroud)

该方案假设文件名中没有空格(这不是一个不寻常的限制;避免名称中的空格问题相对棘手).而且,没有必要echo; 写吧:

for file in $(find "$logDir" -type f)
Run Code Online (Sandbox Code Playgroud)

继续:

do
    name=eval basename $file
Run Code Online (Sandbox Code Playgroud)

这将运行basename命令,并将环境变量name设置为值eval和参数$file.你需要的是:

    name=$(basename "$file")
Run Code Online (Sandbox Code Playgroud)

双引号不是绝对必要的,因为名称不能包含空格(但引用所有文件名并不是一个坏习惯,因为有时名称确实包含空格).

    echo $name
Run Code Online (Sandbox Code Playgroud)

这将回显空行,因为未设置名称.

    name=$(echo $name | sed 's/.$//')
Run Code Online (Sandbox Code Playgroud)

如果设置了名称,这将切断最后一个字符,但如果名称是A,则你什么也没有留下.

    echo $tempDir
    opFile=$tempDir$name
    echo $opFile
done
Run Code Online (Sandbox Code Playgroud)

给出或采用双引号以及你没有添加_tmp后缀的事实,opFile其余的没有任何问题.

合成

将更改放在一起,您最终得到:

tempDir=./tmp/
logDir=./logs/

for file in $(find "$logDir" -type f)
do
    name=$(basename "$file")
    echo "$name"                    # Debug only
    echo "$tempDir"                 # Debug only
    opFile="$tempDir${name}_tmp"
    echo "$opFile"
done
Run Code Online (Sandbox Code Playgroud)

这显示了所有中间结果.你可以很好地将其压缩到:

tempDir=./tmp/
logDir=./logs/

for file in $(find "$logDir" -type f)
do
    opFile="$tempDir"$(basename "$file")"_tmp"
    echo "$opFile"
done
Run Code Online (Sandbox Code Playgroud)

或者,使用双引号的简单组合,因为名称不包含空格:

tempDir=./tmp/
logDir=./logs/

for file in $(find "$logDir" -type f)
do
    opFile="$tempDir$(basename $file)_tmp"
    echo "$opFile"
done
Run Code Online (Sandbox Code Playgroud)

当然,echo是作为您计划执行的复制或移动操作的代理.

编辑:...并删除包含空格和通配符的文件名限制,请执行以下操作:

tempDir=./tmp/
logDir=./logs/

find "$logDir" -type f |
while IFS= read -r file
do
    opFile="${tempDir}${file##*/}_tmp"
    echo "$opFile"
done
Run Code Online (Sandbox Code Playgroud)

对于包含换行符的文件名,它仍然会失败.如果你想处理它,那么使用find ... -print0 | xargs -0或调查解决方案find ... -exec.