首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用bash时,我需要删除文件扩展名前的尾随空格。

使用bash时,我需要删除文件扩展名前的尾随空格。
EN

Stack Overflow用户
提问于 2015-03-24 00:45:38
回答 4查看 2.2K关注 0票数 4

我有数百个类似于以下文件的文件:

代码语言:javascript
复制
"QDN34 Unit5 mark-up - Judy .pdf"  
"QDN34 Unit7 mark-up - Judy .pdf"  
"file with two character ext .ai"  
"file with dot. trailing space and no ext "  
"file with no ext"

请注意,除最后一处外,所有文件的末尾都有一个空格,相关时不包括文件扩展名。

我需要保留文件名中的空格(不理想),并删除那些尾随空格。

结果应该是:

代码语言:javascript
复制
"QDN34 Unit5 mark-up - Judy.pdf"
"QDN34 Unit7 mark-up - Judy.pdf"  
"file with two character ext.ai"  
"file with dot. trailing space and no ext"  
"file with no ext"

到目前为止,我已经:

代码语言:javascript
复制
newName=$(find . -type f -name \*\ .* | cut -d'.' -f2 | sed 's/\ $//' | sed 's/^\/*//')
extens=$(find . -type f -name \*\ .* | sed 's@.*/.*\.@.@')
oldName=$(find . -type f -iname \*\ .* | sed 's/^\.\/*//')
for f in "$oldName" ; do mv -nv "$oldName" "$newName""$extens" ; done

但是我得到了一些错误,这些错误看上去像是索引不匹配。我觉得我应该使用数组,但我不确定如何使用。

产出如下:

代码语言:javascript
复制
mv: rename file with two character ext .ai  
QDN34 Unit5 mark-up - Judy .pdf  
QDN34 Unit7 mark-up - Judy .pdf to file with two character ext  
QDN34 Unit5 mark-up - Judy  
QDN34 Unit7 mark-up - Judy.ai  
.pdf  
.pdf: No such file or directory
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-03-24 05:56:45

巴什溶液

在这种情况下,Bash解决方案可能也很有用。下面是对脚本中带有max 4 chars + .的扩展( extsz )设置的测试。如果找到扩展名,脚本会从文件名中删除空白,然后将文件从旧名称移到新名称(下面注释为实际移动)。它依赖于参数展开/子字符串替换来操作空格和文件名:

代码语言:javascript
复制
#!/bin/bash

declare -i extsz=-5     # extension w/i last 4 chars

## trim leading/trailing whitespace
function trimws {
    [ -z "$1" ] && return 1
    local strln="${#1}"
    [ "$strln" -lt 2 ] && return 1
    local trimstr=$1
    trimstr="${trimstr#"${trimstr%%[![:space:]]*}"}"  # remove leading whitespace characters
    trimstr="${trimstr%"${trimstr##*[![:space:]]}"}"  # remove trailing whitespace characters
    printf "%s" "$trimstr"
    return 0
}

## for each filename read from stdin
while read -r ffname || test -n "$ffname" ; do

    ## test for extension and set 'ext' if present
    for ((i=$extsz; i<0; i++)); do
        [ "${ffname:(i):1}" == '.' ] && { ext=${ffname:(i)}; break; }
    done

    ## if extension, move the file to name w/o trailing space w/orig extension
    if [ -n "$ext" ]; then

        fname="${ffname%.*}"          # separate filename from extension
        fnwosp="$(trimws "$fname")"   # trim whitespace from filename

        printf "   renaming :  '%s' -> '%s'\n" "$ffname" "${fnwosp}${ext}"
        #mv "$ffname" "${fnwosp}${ext}"  # commented for testing

    else
        ## if no extension, just trim whitespace and move
        printf "   renaming :  '%s' -> '%s'\n" "$ffname" "$(trimws "$ffname")"
        # mv "$ffname" "$(trimws "$ffname")"
    fi

    unset ext       # unset 'ext' for next iteration

done

exit 0

输入

代码语言:javascript
复制
$ cat dat/wfname.txt
QDN34 Unit5 mark-up - Judy .pdf
QDN34 Unit7 mark-up - Judy .pdf
file with two character ext .ai
file with dot. trailing space and no ext
file with no ext

输出

代码语言:javascript
复制
$ bash fixfilenames.sh <dat/wfname.txt
   renaming :  'QDN34 Unit5 mark-up - Judy .pdf' -> 'QDN34 Unit5 mark-up - Judy.pdf'
   renaming :  'QDN34 Unit7 mark-up - Judy .pdf' -> 'QDN34 Unit7 mark-up - Judy.pdf'
   renaming :  'file with two character ext .ai' -> 'file with two character ext.ai'
   renaming :  'file with dot. trailing space and no ext' -> 'file with dot. trailing space and no ext'
   renaming :  'file with no ext' -> 'file with no ext'

注意:当从stdin读取时,shell将去掉文件名的尾随空格,而不需要扩展。

读取文件名为参数

为了说明在没有扩展的情况下从文件名末尾删除空格,有必要将文件名作为参数引用和读取。如果这是你需要的,这是一个替代。将文件名作为参数而不是从stdin大量读取可能更有意义:

代码语言:javascript
复制
#!/bin/bash

declare -i extsz=-5     # extension w/i last 4 chars

## trim leading/trailing whitespace
function trimws {
    [ -z "$1" ] && return 1
    local strln="${#1}"
    [ "$strln" -lt 2 ] && return 1
    local trimstr=$1
    trimstr="${trimstr#"${trimstr%%[![:space:]]*}"}"  # remove leading whitespace characters
    trimstr="${trimstr%"${trimstr##*[![:space:]]}"}"  # remove trailing whitespace characters
    printf "%s" "$trimstr"
    return 0
}

## test at least 1 command line argument
[ $# -gt 0 ] || {
    printf "error: insufficient input.  usage: %s <filename>\n" "${0##*/}"
    exit 1
}

## for each of the filenames give as arguments
for ffname in "$@"; do

    ## test for extension and set 'ext' if present
    for ((i=$extsz; i<0; i++)); do
        [ "${ffname:(i):1}" == '.' ] && { ext=${ffname:(i)}; break; }
    done

    ## if extension, move the file to name w/o trailing space w/orig extension
    if [ -n "$ext" ]; then

        fname="${ffname%.*}"          # separate filename from extension
        fnwosp="$(trimws "$fname")"   # trim whitespace from filename

        printf "   renaming :  '%s' -> '%s'\n" "$ffname" "${fnwosp}${ext}"
        #mv "$ffname" "${fnwosp}${ext}"  # commented for testing

    else

        ## if no extension, just trim whitespace and move
        printf "   renaming :  '%s' -> '%s'\n" "$ffname" "$(trimws "$ffname")"
        # mv "$ffname" "$(trimws "$ffname")"

    fi

    unset ext

done

exit 0

示例

代码语言:javascript
复制
$ bash fixfilenames.sh 'testfile w end space '
   renaming :  'testfile w end space ' -> 'testfile w end space'

$ bash fixfilenames.sh 'file with two character ext .ai'
   renaming :  'file with two character ext .ai' -> 'file with two character ext.ai'
票数 1
EN

Stack Overflow用户

发布于 2015-03-24 01:12:21

您可以使用以下的prename实用程序来尝试

代码语言:javascript
复制
user@host $ prename 's/\s(\..+$)/$1/g' *
  • \s -意为空间字符
  • \. -均值点
  • . -意思是一个字符
  • +$ --意思是重复前面的符号到行尾。
  • $1 -意思是用()中的表达式替换

如果您没有这个实用程序,可以使用以下bash脚本:

代码语言:javascript
复制
# you can replace the "*" in the line below
# with any necessary find or ls command to rename only necessary files
for old_name in *;
do
    new_name=$(echo "$old_name"|sed 's/ \(\.[^ \t]*$\)/\1/g')
    echo "\"$old_name\" --> \"$new_name\""
    mv "$old_name" "$new_name" 
done
票数 1
EN

Stack Overflow用户

发布于 2015-03-24 02:44:35

代码语言:javascript
复制
#!/bin/bash
IFS=$(echo -en "\n\b") && for a in $(ls -f1 *); do 
file_ext="${a##*.}"
if [[ ! -z "${file_ext}" && ${#file_ext} -lt 4 ]]; then 
 file_base="${a%.*}"
else 
 file_base="${a}" 
 file_ext=""
fi 
[ "${file_base:$((${#file_base}-1)):1}" = " " ] && \
 file_base="${file_base% *}"
new_file="${file_base}${file_ext:+.}${file_ext}" 
if [ ! "${new_file}" = "${a}" ]; then 
 echo "mv -nv \"$a\" \"${new_file}\"" 
 #mv -nv "${a}" "${file_base}.${file_ext}"
fi 
done 

您可以在希望重命名它们的目录中安全地运行这个bash脚本,以查看它将做什么,然后如果它将完成您想要的任务,您可以取消对真正的move命令的注释并重新运行它。

更新每个OP注释-这个脚本考虑到一个文件扩展名最多为3(小于4)的.必须从右边修改,以反映您的数据集。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29223056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档