我一直在命名文件,作为程序员在服务器命令行上工作的习惯,下划线“ _
”而不是空格“ ” - 因为从命令行你必须转义空格 - 但这在命令行之外是不必要的很快就变老了。我想在切换到空间的同时保持一切均匀。
从“终端”,我想知道如何在Mac OS X上的特定目录的文件名中将所有“x”转换为“y”?请注意,“x”表示任何内容,“y”只是一个空格。
我想以递归方式执行此操作,处理所有子目录,而不是一次只处理一个文件夹。
我一直在命名文件,作为程序员在服务器命令行上工作的习惯,下划线“ _
”而不是空格“ ” - 因为从命令行你必须转义空格 - 但这在命令行之外是不必要的很快就变老了。我想在切换到空间的同时保持一切均匀。
从“终端”,我想知道如何在Mac OS X上的特定目录的文件名中将所有“x”转换为“y”?请注意,“x”表示任何内容,“y”只是一个空格。
我想以递归方式执行此操作,处理所有子目录,而不是一次只处理一个文件夹。
Answers:
从“终端”,我想知道如何在Mac OS X上的特定目录的文件名中将所有“x”转换为“y”?请注意,“x”表示任何内容,“y”只是一个空格。
我想以递归方式执行此操作,处理所有子目录,而不是一次只处理一个文件夹。
调整sed
@meatspace 在他的评论(位于此页面上)引用的一些基本概念并添加find
到混合中我想出了这个脚本:
find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f |\
while read FULL_ITEM_PATH
do
FILE_DIRNAME=$(dirname "${FULL_ITEM_PATH}");
FILE_BASENAME=$(basename "${FULL_ITEM_PATH}");
mv "${FILE_DIRNAME}"/"${FILE_BASENAME}" "${FILE_DIRNAME}"/"$(echo $FILE_BASENAME | sed -e 's/_/ /g')";
done
这将用于find
查找您所在的当前目录中的所有文件(包括子目录/文件),然后在文件名(_
)中搜索下划线并根据需要将它们更改为spaces()。该脚本忽略“点文件”/“不可见文件”,如
.DS_Store
via -prune -o -not -name '.*'
,然后核心逻辑仅作用于实际文件名 - 而不是目录名 - 通过将文件基名与目录名分开。
我在我的Mac OS X 10.9.5(Mavericks)机器上创建了一个测试目录树,其中包含_
名称中包含下划线()的文件- 其中一些嵌套在子目录中 - 如下所示:
./foo_bar
./foo_bar_two
./foo_bar_two_three
./foo_bar_two_three_bleagh.txt
./nested/foo_bar
./nested/foo_bar_two
./nested/foo_bar_two_three
./nested/foo_bar_two_three_bleagh.txt
./nested_foo/foo_bar
./nested_foo/foo_bar_two
./nested_foo/foo_bar_two_three
./nested_foo/foo_bar_two_three_bleagh.txt
然后我运行该脚本,它们都被自动更改为使用space(),如下所示:
./foo bar
./foo bar two
./foo bar two three
./foo bar two three bleagh.txt
./nested/foo bar
./nested/foo bar two
./nested/foo bar two three
./nested/foo bar two three bleagh.txt
./nested_foo/foo bar
./nested_foo/foo bar two
./nested_foo/foo bar two three
./nested_foo/foo bar two three bleagh.txt
虽然脚本有效,但如果你想做一个简单的“干运行”来查看脚本将采取什么行动,请将mv
命令替换为echo
:
find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f |\
while read FULL_ITEM_PATH
do
FILE_DIRNAME=$(dirname "${FULL_ITEM_PATH}");
FILE_BASENAME=$(basename "${FULL_ITEM_PATH}");
echo "${FILE_DIRNAME}"/"${FILE_BASENAME}" "${FILE_DIRNAME}"/"$(echo $FILE_BASENAME | sed -e 's/_/ /g')";
done
使用echo
调试的好处是你还可以确切地看到脚本核心中发生了什么。因此,虽然我编写了这个脚本以满足此问题中指定的确切需求,但如果它们出现,请随意尝试使其适应新的需求/想法。
mv: rename ./Springhill/WPCS_Head_Start_Pre-School/WPCS_Head_Start_Pre-School_Office_Systems/.DS_Store to ./Springhill/WPCS Head Start Pre-School/WPCS Head Start Pre-School Office Systems/.DS Store: No such file or directory
sed
仅对文件名运行逻辑,然后用于mv
移动/重命名文件而不对目录执行操作。我还添加了逻辑来忽略不可见的文件.DS_Store
; 基本上任何.
以名称开头的文件。
-depth
,find
以便在更改其中的文件之前不要更改更高级别的目录(文件夹)名称。
在相关目录中时:
for f in in *; do echo mv "$f" "${f/_*_/ }"; done
这将列出要进行的更改 - echo
当您希望它实际进行重命名时删除。像所有* nix一样,有一百万种方法可以做到这一点,但上面的内容非常明确。如果您经常执行此任务,请考虑将其另存bin
为脚本。
foo_bar_baz.txt
将重命名foo baz.txt
为例如。考虑${f//_/ }
用空格替换所有下划线而不修改文件名。
我可能会用Perl来做。
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
sub rename_files {
#skip directories
return if -d $File::Find::name;
my $newname = $File::Find::name;
#turn underscores into space.
$newname =~ s/_/ /g;
rename $File::Find::name, $newname;
}
find ( \&rename_files, 'path_to_change' );
这个班轮怎么样?(我希望在这里粘贴我的命令不会搞砸空间)
for f in `find . -type f -name '*_*'` ; do echo mv "$f" "${f//_/ }"; done
我尝试时似乎工作。(准备好后你需要删除那个回声)
不进行任何目录重命名。我想那就是你想要的?递归似乎工作正常。还可以正确处理多个下划线。
有多个shell:
david_koontz @ Macbook:更多〜/ bin / rename
#!/bin/csh -f
if ( $1 != "" && $2 != "" ) then
foreach file ( `ls *$1*` )
setenv target `echo $file | sed s/"$1"/"$2"/`
if ( -f $file ) then
echo renaming $file to $target
mv $file $target
endif
end
else
echo "usage: $0 src_pattern_match dest_pattern_substitution"
exit -1
endif
exit 0
对于递归重命名:
#!/bin/csh -f
if ( $1 != "" && $2 != "" ) then
# limit the depth search with -maxdepth:
foreach file ( `find . -maxdepth 8 -iname \*$1\* -type f -exec echo \{\} \;`)
setenv filehead $file:h
setenv filetail $file:t
setenv targettail `echo $filetail | sed s/"$1"/"$2"/`
echo renaming $file $filehead/$targettail
mv $file $filehead/$targettail
end
else
"usage: $0 src_pattern_match dest_pattern_substitution"
exit -1;
endif
exit 0;
对于recursive_rename,您可以使用可选的$ 3来传递最大深度或消除-maxdepth 8
,这提供了递归深度限制。
您可以添加一个可以添加的选项,-i
也mv
可以使用和可选参数来启用交互式重命名。