【问题标题】:Create folders with names of files present in folder then move those files in each of that folder使用文件夹中存在的文件名创建文件夹,然后在每个文件夹中移动这些文件
【发布时间】:2024-01-05 12:43:01
【问题描述】:

abc 文件夹中存在不同的文件(每个文件的扩展名不同),我想根据该文件夹中存在的文件名创建文件夹并将这些文件移动到相应的文件夹中。 例如:

文件夹abc

2.0261fc5a.js.1
22b8a.0cb8dc71bas.map
318a.fa1253sdfde99265.js.map.1
s3ds.asdasg.asfgsf.afasdf.sd

具有唯一名称的文件。

我要创作

2.0261fc5a.js.1 文件夹并在该文件夹中移动 2.0261fc5a.js.1 文件 同样,所有文件都应该发生这种情况。 我做了一些研究并找到了这个解决方案。

tmp=`mktemp -d tmp_XXXXXX` || exit 1
for i in *
do
  mv "$i" $tmp
done
mv $tmp/* .
rm -r $tmp

但这会产生错误 mv: cannot move 'tmp_RwK2xZ' to a subdirectory of itself, 'tmp_RwK2xZ/tmp_RwK2xZ'

你们能帮忙解决一下吗?

【问题讨论】:

  • 简单地说,您不能将目录命名为与您打算放入其中的文件完全相同的名称。
  • 嘿@l'L'l 你能详细说明一下吗
  • 您正试图将目录mktemp 移动到其自身中。您实际上需要将类似名称的文件移动到目录中。

标签: bash terminal sh


【解决方案1】:

我会使用 tmp file 而不是 tmp dir

tmpfile=$(mktemp)   # TODO, check this exists on the same filesystem,
                    # or provide a template argument
for file in *; do
  if [[ $file != "$tmpfile" ]]; then
    mv "$file" "$tmpfile"
    mkdir "$file"         # TODO check for failure
    mv "$tmpfile" "$file/$file"
  fi
done

剩下要做的事情:如果出现错误消息并重新命名文件。

【讨论】:

    【解决方案2】:

    也许你可以使用find

    find . -type f -maxdepth 1 -exec mv {} {}_temp \; -exec mkdir {} \; -execdir mv {}_temp {}/{} \;
    

    这个命令对名为abc的文件的作用:

    mv ./abc ./abc_temp
    mkdir ./abc
    mv ./abc_temp ./abc/./abc
    

    通过添加_temp重命名文件,创建一个名为原始文件的目录,最后在临时文件移入目录时将其重命名。

    【讨论】:

      【解决方案3】:

      对于当前目录中的每个元素fname

      • 如果该元素是文件:if [ -f $fname ]
      • 暂时将文件移动到/tmpmv $fname /tmp
      • 创建一个与fname同名的目录:mkdir $fname
      • fname 移动到该目录:mv /tmp/$fname ./$fname/
      for fname in *
      do
          if [ -f "$fname" ]
          then
              mv "$fname" /tmp
              mkdir "$fname"
              mv "/tmp/$fname" "./$fname/"
          fi
      done
      

      为什么到处都是双引号?

      空格,空格,空格。有时文件名有空格。这使得problems。双引号是解决方案。

      什么是/tmp

      我们将文件从当前目录移动到临时目录,这样它就不会与我们将要创建的同名文件夹冲突。我们不必创建新文件或文件夹来存储任何内容,因为 linux /tmp 正是为此目的而存在的。临时存储随机的东西:)

      【讨论】:

      • 你应该在for循环声明($(find . -maxdepth 1 -type f))中双引号命令以避免word splitting
      • 好收获!我实际上发现使用* 更容易,然后检查元素是否为文件