c shell 脚本:查找目录并重命名查找的输出
c shell script: find directory and rename the output of find
我对这个 shell 脚本还是陌生的。我有一项任务交给我,但我很难执行它。
任务是我有很多基于 ddmmyy 的目录。
03Mar2014 08Aug2013 11Jan2015 16Jan2014 22Feb2014 26Mar2014
03Nov2013 08Jan2014 11Jul2013 16Jul2013 22Jul2013 26Oct2014
03Oct2013 08Jan2015 11Nov2014 16May2014 22Mar2014 26Sep2013
任务是把目录做成mmyy
到目前为止,我的代码是
foreach file(`find . -type d | awk -F/ 'NF == 3'`)
echo $file
set newmove = `echo $file | cut -c 1-2,5-`
echo $newmove
mv $file $newmove
output:
for find . -type d | awk -F/ 'NF == 3':
./24Jan2015/W51A
`echo $file | cut -c 1-2,5-`
./Jan2015/W51A
mv $file $newmove
mv: cannot rename ./24Jan2015/W51A to ./Jan2015/W51A: No such file or directory
但是脚本不起作用。
你们知道怎么做吗?
首先,问题是您正在重命名文件,但实际上是在尝试重命名目录,因此出现错误。
据我所知,这个想法是将当前工作目录中的文件夹重命名为所需的格式,这样实际上将文件夹的内容从相同的 mmYYYY 格式合并到新格式(因为 11Jan2015 和 16Jan2014 将重命名为 Jan2014)
你可以试试这个:
foreach dir ( `ls` )
set newdir = `echo $dir| cut -c 3-`
mkdir -p $newdir
mv -f $dir/* $newdir
rmdir $dir
end
-p 将创建文件夹,如果文件夹已经存在则什么也不做。
一些假设:
- 文件夹在同一个地方
pwd
- 日期总是有两个前导数字
- 您要合并相同 mmYYYY 格式的文件夹内容
- 不同文件夹中的同名文件将被覆盖
- pwd里面只有文件夹(如果不是则添加检查)
如果这些文件夹位于不同的位置(根据您的输出并非如此:./24Jan2015)并且冲突不是问题 - 应该更改代码至:
- 使用查找
- 使用正确的路径创建新文件夹
不会发生合并和覆盖,因此 1、3、4 和 5 不相关。
更新:
额外输入后 - 如果我理解正确,你的查找只查找深度为 3 的文件夹。我不能说为什么,但你可以使用
更快地实现相同的目的
find . -type d -mindepth=2 -maxdepth=2
输出是包含子文件夹的文件夹列表。
然后您需要获取第二个文件夹的名称(假设它始终是预期的格式)。
set olddir = `echo $file| cut -f 1-3 -d '/'`
set newdir = `echo $olddir | cut -c 1-2,5-`
最后
foreach file(`find . -type d -mindepth=2 -maxdepth=2`)
set olddir = `echo $file| cut -f 1-3 -d '/'`
set newdir = `echo $olddir | cut -c 1-2,5-`
mkdir -p $newdir
mv -f $file $newdir
end
如果在同一路径下发现两个文件夹,这也将处理这种情况。
更新 2:
由于该脚本将 运行 在 Unix 上运行 - 应进行以下更新:
- 返回原始查找,因为 unix 查找缺少 mindepth/maxdepth 选项
- 我们应该尝试删除 olddir 以清理空文件夹 - 如果文件夹不为空,它将失败,但脚本应该继续 运行
foreach file(`find . -type d | awk -F/ 'NF == 3'`)
set olddir = `echo $file| cut -f 1-2 -d '/'`
set newdir = `echo $olddir | cut -c 1-2,5-`
set dir_name=`basename "$file"`
if ( -d "$newdir/$dir_name" ) then
mv -f $file/* $newdir/$dir_name/
else
mkdir -p $newdir
mv -f $file $newdir
endif
rmdir $olddir
end
我真的认为 c shell 是任何涉及编程的错误工具。也就是说,这看起来只需要外部工具的一点帮助就可以做你想做的事:
#!/bin/csh
foreach file ([0-9][0-9][A-Z][a-z][a-z][0-9][0-9][0-9][0-9])
set new = `echo $file:q | cut -c 3-`
if ( -d "$new" ) then
echo "skipping $file because $new already exists"
continue
endif
mv -v "$file" "$new"
end
注意与您要重命名的目录列表匹配的 glob。该脚本不会费心去确认匹配的文件是否实际上是目录,所以如果它们可能不是,您应该以某种方式考虑到这一点。
请注意,我们使用反引号表达式来使用外部工具,cut
从每个目录名称中获取子字符串。我们使用它(就像您在问题中所做的那样)是因为 CSH 不是一种编程语言,并且没有自己的字符串处理能力。
循环中的if
语句将跳过目标已存在的任何目录。因此,例如,如果您要遍历问题中输入的第一行,26Mar2014 将转换为 Mar2014,由于 03Mar2014 已经存在。由于您尚未指定应如何处理,此脚本会跳过该条件。
我对这个 shell 脚本还是陌生的。我有一项任务交给我,但我很难执行它。 任务是我有很多基于 ddmmyy 的目录。
03Mar2014 08Aug2013 11Jan2015 16Jan2014 22Feb2014 26Mar2014
03Nov2013 08Jan2014 11Jul2013 16Jul2013 22Jul2013 26Oct2014
03Oct2013 08Jan2015 11Nov2014 16May2014 22Mar2014 26Sep2013
任务是把目录做成mmyy
到目前为止,我的代码是
foreach file(`find . -type d | awk -F/ 'NF == 3'`)
echo $file
set newmove = `echo $file | cut -c 1-2,5-`
echo $newmove
mv $file $newmove
output:
for find . -type d | awk -F/ 'NF == 3':
./24Jan2015/W51A
`echo $file | cut -c 1-2,5-`
./Jan2015/W51A
mv $file $newmove
mv: cannot rename ./24Jan2015/W51A to ./Jan2015/W51A: No such file or directory
但是脚本不起作用。 你们知道怎么做吗?
首先,问题是您正在重命名文件,但实际上是在尝试重命名目录,因此出现错误。
据我所知,这个想法是将当前工作目录中的文件夹重命名为所需的格式,这样实际上将文件夹的内容从相同的 mmYYYY 格式合并到新格式(因为 11Jan2015 和 16Jan2014 将重命名为 Jan2014)
你可以试试这个:
foreach dir ( `ls` )
set newdir = `echo $dir| cut -c 3-`
mkdir -p $newdir
mv -f $dir/* $newdir
rmdir $dir
end
-p 将创建文件夹,如果文件夹已经存在则什么也不做。
一些假设:
- 文件夹在同一个地方
pwd
- 日期总是有两个前导数字
- 您要合并相同 mmYYYY 格式的文件夹内容
- 不同文件夹中的同名文件将被覆盖
- pwd里面只有文件夹(如果不是则添加检查)
如果这些文件夹位于不同的位置(根据您的输出并非如此:./24Jan2015)并且冲突不是问题 - 应该更改代码至:
- 使用查找
- 使用正确的路径创建新文件夹
不会发生合并和覆盖,因此 1、3、4 和 5 不相关。
更新: 额外输入后 - 如果我理解正确,你的查找只查找深度为 3 的文件夹。我不能说为什么,但你可以使用
更快地实现相同的目的find . -type d -mindepth=2 -maxdepth=2
输出是包含子文件夹的文件夹列表。
然后您需要获取第二个文件夹的名称(假设它始终是预期的格式)。
set olddir = `echo $file| cut -f 1-3 -d '/'`
set newdir = `echo $olddir | cut -c 1-2,5-`
最后
foreach file(`find . -type d -mindepth=2 -maxdepth=2`)
set olddir = `echo $file| cut -f 1-3 -d '/'`
set newdir = `echo $olddir | cut -c 1-2,5-`
mkdir -p $newdir
mv -f $file $newdir
end
如果在同一路径下发现两个文件夹,这也将处理这种情况。
更新 2:
由于该脚本将 运行 在 Unix 上运行 - 应进行以下更新:
- 返回原始查找,因为 unix 查找缺少 mindepth/maxdepth 选项
- 我们应该尝试删除 olddir 以清理空文件夹 - 如果文件夹不为空,它将失败,但脚本应该继续 运行
foreach file(`find . -type d | awk -F/ 'NF == 3'`) set olddir = `echo $file| cut -f 1-2 -d '/'` set newdir = `echo $olddir | cut -c 1-2,5-` set dir_name=`basename "$file"` if ( -d "$newdir/$dir_name" ) then mv -f $file/* $newdir/$dir_name/ else mkdir -p $newdir mv -f $file $newdir endif rmdir $olddir end
我真的认为 c shell 是任何涉及编程的错误工具。也就是说,这看起来只需要外部工具的一点帮助就可以做你想做的事:
#!/bin/csh
foreach file ([0-9][0-9][A-Z][a-z][a-z][0-9][0-9][0-9][0-9])
set new = `echo $file:q | cut -c 3-`
if ( -d "$new" ) then
echo "skipping $file because $new already exists"
continue
endif
mv -v "$file" "$new"
end
注意与您要重命名的目录列表匹配的 glob。该脚本不会费心去确认匹配的文件是否实际上是目录,所以如果它们可能不是,您应该以某种方式考虑到这一点。
请注意,我们使用反引号表达式来使用外部工具,cut
从每个目录名称中获取子字符串。我们使用它(就像您在问题中所做的那样)是因为 CSH 不是一种编程语言,并且没有自己的字符串处理能力。
循环中的if
语句将跳过目标已存在的任何目录。因此,例如,如果您要遍历问题中输入的第一行,26Mar2014 将转换为 Mar2014,由于 03Mar2014 已经存在。由于您尚未指定应如何处理,此脚本会跳过该条件。