首先,我有这样一个剧本:
#!/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问题是:它只适用于名称单一的文件。“一”变“英”,“二”变“子”,“一二”不成“银子”。如何用包含多个单词的名称重命名文件,例如“我的文档”、“第一个文件夹”等等?我知道我必须以某种方式标记文件夹名,但不要知道如何实现。初出茅庐。提前谢谢。
发布于 2014-12-16 12:25:25
这里有一个非常普通的纯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。
发布于 2014-12-16 11:11:14
如果您有perl rename/prename命令& 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只指定目录,即“1 2”和“2”,忽略文件“1”。
发布于 2014-12-16 10:06:11
使用适当的引语
mv "$i" "$(grep $i names.txt | cut -d ' ' -f 2)"双引号将照顾文件名中的空格。
https://stackoverflow.com/questions/27501995
复制相似问题