【问题标题】:c shell script: find directory and rename the output of findc shell脚本:查找目录并重命名查找的输出
【发布时间】:2016-01-19 22:25:15
【问题描述】:

我还是这个 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

但脚本不起作用。 你们知道如何做到这一点吗?

【问题讨论】:

  • 必须为此您使用 c-shell,或者您可以交替使用 POSIX shell 或 Bash?另外,当您想创建目录“mmyy”时,您真的是指“mmmYYYY”,就像您显示的输入列表一样? CSH programming is sometimes considered harmful.

标签: shell find rename


【解决方案1】:

首先,问题是您正在重命名文件,但实际上试图重命名目录,因此出现错误。

据我了解,我的想法是将当前工作目录中的文件夹重命名为所需的格式,这样实际上将文件夹的内容从相同的 mmYYYY 格式合并到新的格式(自 11Jan201516Jan2014 都将重命名为 Jan2014)

你可以试试这个:

foreach dir ( `ls` )    
   set newdir = `echo $dir| cut -c 3-`

    mkdir -p $newdir
    mv -f $dir/* $newdir
    rmdir $dir
end

-p 将创建文件夹,如果文件夹已存在则不执行任何操作。

一些假设:

  1. 文件夹位于同一位置,即pwd
  2. 日期总是有两个前导数字
  3. 您要合并相同 mmYYYY 格式的文件夹内容
  4. 不同文件夹中的同名文件会被覆盖
  5. pwd 中只有文件夹(如果不是,请添加检查)

如果这些文件夹位于不同的位置(根据您的输出:./24Jan2015,情况并非如此)并且冲突不是问题 - 代码应更改为:

  1. 使用查找
  2. 使用正确的路径创建新文件夹

不会发生合并和覆盖,因此 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 find 缺少 mindepth/maxdepth 选项,返回了原始 find
  • 我们应该尝试删除 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

【讨论】:

  • 谢谢。根据我的脚本,我已经在使用 find 以便具有不同的路径。那么如果删除dd后目录相同,如何制作目录?
  • 如果您想在找到原始文件夹的位置创建它 - 那么您没有问题,因为路径不同。否则,如果您想移动到特定位置 - 使用带有 $some_place/$new_dir 而不是 $new_dir 的脚本,其中 some_place 是特定路径
  • 已更新。但是请注意,您不会找到不同的路径,而只能找到 pwd 中的文件夹以及其中的文件夹。
  • 我正在尝试使用 find 。 -type d -mindepth=2 -maxdepth=2 但我得到错误 find: bad option -mindepth=2 find: [-H | -L] 路径列表谓词列表这就是我使用 find 的原因。 -类型 d | awk -F/'NF == 3'
  • 好吧,那就用你的版本吧。只是想知道 - 你在 Unix 上运行吗?
【解决方案2】:

我真的认为 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 已经存在。由于您尚未指定应如何处理,因此此脚本会跳过该条件。

【讨论】:

  • --v. 的非法选项
  • @wina, --v 不是我使用的选项。尝试一个破折号。这是 BSD、OSX 和 Linux 中的有效选项。如果您正在使用其他东西,请说出来,或者直接放弃该选项。
  • im 使用单破折号 v。出现的错误是 --v 的非法选项
猜你喜欢
  • 2017-02-27
  • 2012-10-13
  • 1970-01-01
  • 2014-02-18
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-10
相关资源
最近更新 更多