【问题标题】:Iterate over folders and move files up one level遍历文件夹并将文件上移一级
【发布时间】:2016-02-22 13:24:48
【问题描述】:

我的目录结构如下所示:

/images
  /1
    /.tmp
      image1.jpg
      image2.jpg
  /2
    .tmp
      image1.jpg
      image2.jpg
      image3.jpg
  /3
    .tmp
      image1.jpg
      image2.jpg

我需要将 .tmp 中的所有这些文件上移一级,因此它们的路径是 images/1/image1.jpg 而不是 images/1/.tmp/image1.jpg。问题是我有成百上千个这样编号的文件夹,所以手动操作会很费时间。

是否有一个 OS X 或 Unix shell 命令我可以遍历每个 /.tmp 文件夹并将内容向上移动一个级别,或者类似的东西:

mv images/*/.tmp/* images/< the current dir being iterated over>/*

【问题讨论】:

    标签: macos bash shell


    【解决方案1】:

    如果您的find 支持-execdir 命令(即OSX's find apparently does),那么您可以这样做:

    find . -iname '*.jpg' -execdir mv {} .. \;
    

    -execdir 从找到文件的目录运行命令,因此.. 将引用该文件目录的父目录。

    您可以对其进行优化以强制匹配.tmp 目录:

    find . -path '*/.tmp/*.jpg' -execdir mv {} .. \;
    

    但是,-path 中的 * 也匹配 /,因此这也会匹配,例如 images/.tmp/foo/image.jpg

    你可以这样做:

    find . -type d -name .tmp -print0 | xargs -0I_ find _ -maxdepth 1 -name '*.jpg' -execdir mv {} .. \;
    

    或者,使用find 的正则表达式支持:

    find . -regex '.*/\.tmp/[^/]*\.jpg' -execdir mv {} .. \;
    

    【讨论】:

    • 是的,刚刚意识到!我以为它只是把文件/路径当作是。
    • 这里唯一需要注意的是,如果在不是.tmp 的目录中还有*.jpg 文件,您也会将它们移动到其他位置。你能调整一下,让它只影响位于.tmp 目录中的文件吗?
    • @muru 您可以使用正则表达式代替路径或管道。
    • @123 嗯,是的,-regex '.*/\.tmp/[^/]*\.jpg' 应该足够了。谢谢提醒。
    【解决方案2】:

    从头开始,无需测试:

    cd /images
    for i in $(find ./ -name *.jpg)
    do
    d = $(dirname $i)
    d = $(dirname $d)
    echo $i $d
    # test! before use the next
    # mv $i $d
    done
    

    【讨论】:

    • 永远不要这样做:for x in $(command)command$var。 for-in 用于迭代参数,而不是(输出)字符串。相反,请使用 glob(例如 *.txt)、数组(例如 "${names[@]}")或 while-read 循环(例如 while read -r line)。见mywiki.wooledge.org/BashPitfalls#pf1mywiki.wooledge.org/DontReadLinesWithFor
    • 使用find,使用读取的方式是find … -print0 | while IFS= read -d '' -r i; do …
    猜你喜欢
    • 2018-12-23
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多