开始我有这样一个剧本:
#!/bin/bash
for i in *; do
if [ -d "$i" ]; then
if [ "$i" == $(grep $i names.txt | cut -d ' ' -f 1) ]; then
mv $i $(grep $i names.txt | cut -d ' ' -f 2)
else
echo "The word $i wasn't found in the dictionary"
fi
fi
done
使用字典(names.txt)重命名文件,哪一行是模式" english_word german_one"。
one eins
two zwei
my mein
your dein
问题是:它仅适用于名称单字的文件。 "一个"成为" eins", " 2"变成" zwei",但是"一个两个"不会成为" eins zwei"。 如何重命名名称包含多个单词的文件,例如"我的文档","第一个文件夹"等? 我知道我必须以某种方式标记文件夹名称,但不知道如何。 bash的新手。 提前谢谢。
答案 0 :(得分:2)
这是一个相当普遍的纯Bash解决方案:我们将文件夹名称标记化,然后对名称中的每个单词执行翻译。在此之前,我们将字典加载到哈希数组中:
#!/bin/bash
# load dictionary
declare -A dictionary=()
while read -r eng ger; do
[[ $eng ]] && [[ $ger ]] || continue
dictionary[$eng]=$ger
done < dictionary_file
tokenize() {
# Split $1 into two arrays:
# tokenize_sep consists of all the non-alpha strings
# tokenize_alpha consists of all the alpha strings
# We have: $1=${tokenize_sep[0]}${tokenize_alpha[0]}${tokenize_sep[1]}${tokenize_alpha[1]} ...
local var=$1
tokenize_sep=() tokenize_alpha=()
while [[ $var ]]; do
[[ $var =~ ([^[:alpha:]]*)(.*) ]]
tokenize_sep+=( "${BASH_REMATCH[1]}" )
var=${BASH_REMATCH[2]}
[[ $var =~ ([[:alpha:]]*)(.*) ]]
tokenize_alpha+=( "${BASH_REMATCH[1]}" )
var=${BASH_REMATCH[2]}
done
}
translate_ary() {
# Translates each word given as arguments according to hash array dictionary
# Returned array is translate_ary_ret
local w t
translate_ary_ret=()
for w; do
if [[ $w ]]; then
t=${dictionary[$w]}
[[ $t ]] || t=$w
else
t=
fi
translate_ary_ret+=( $t )
done
}
intertwine() {
# $1 and $2 are two array names
# returns a string intertwine_ret that consists of all fields of $1 and $2 intertwined (shuffled)
local ary1=$1[@] ary2=$2[@] i
ary1=( "${!ary1}" ) ary2=( "${!ary2}" )
intertwine_ret=
for((i=0;i<${#ary1[@]};++i)); do
intertwine_ret+=${ary1[i]}${ary2[i]}
done
}
translate() {
# Translates string given in $1, preserving separators
# Return string in translate_ret
tokenize "$1"
translate_ary "${tokenize_alpha[@]}"
intertwine tokenize_sep translate_ary_ret
translate_ret=$intertwine_ret
}
# Do the renaming:
for i in *; do
translate "$i"
[[ $i = "$translate_ret" ]] && continue
echo mv -nv -- "$i" "$translate_ret"
done
它不是真正的单行,但应该完成这项工作。
我将此脚本称为banana
,chmod +x
并且:
$ ls -1
banana
banana_is_my_favorite_fruit
dictionary_file
--one..my^ your-banana.one
one_two_bananas
your_two...pdf
$ ./banana
mv -nv -- banana_is_my_favorite_fruit banana_is_mein_favorite_fruit
mv -nv -- --one..my^ your-banana.one --eins..mein^ dein-banana.eins
mv -nv -- one_two_bananas eins_zwei_bananas
mv -nv -- your_two...pdf dein_zwei...pdf
没有移动任何内容:为此,请删除脚本底部echo
命令前面的mv
。
答案 1 :(得分:1)
如果你有perl rename/prename
命令&amp; awk随你而来,试试这个单行:
$ touch one; mkdir -p "one two" two # "one two" & two are directories, one is file.
$ ls -F # verify. This would probably how your structure look like.
names.txt one "one two/" two/ #<~~~~"one two" quoted only for the explanation. ls does not quote it.
$ prename "$(awk '{printf "s/"$1"/"$2"/g;"}' names.txt )" */ # This will rename as per your requirement.
$ ls -F # verify
"eins zwei/" names.txt one zwei/ #<~~~~ same quoting here too...
说明:
$ awk '{printf "s/"$1"/"$2"/g;"}' names.txt # generates the find/replace perl regex.
s/one/eins/g;s/two/zwei/g;s/my/mein/g;s/your/dein/g;
prename
然后重命名使用perl-regex提供的文件。
*/
glob仅指定目录,即&#34;一个两个&#34; &安培; &#34;两个&#34;,忽略文件&#34;一个&#34;。
答案 2 :(得分:0)
使用正确的引语
mv "$i" "$(grep $i names.txt | cut -d ' ' -f 2)"
双引号将处理文件名中的空格
答案 3 :(得分:0)
在谷歌踢了一段时间之后,我找到了这样的解决方案:
#!/bin/bash
for i in *; do
if [ -d "$i" ]; then
newname=""
del=""
for word in $i; do
if [ "$word" == "$(grep $word names.txt | cut -d ' ' -f 1)" ]; then
newname="$newname""$del""$(grep $word names.txt | cut -d ' ' -f 2)"
else
newname="$newname""$del""$word"
fi
del=" "
done
if [ "$i" != "$newname" ]; then
mv "$i" "$newname"
fi
fi
done