【问题标题】:Convert ls output into csv将 ls 输出转换为 csv
【发布时间】:2013-01-28 23:38:19
【问题描述】:

我将如何转换:

$ find . -ls > /tmp/files.txt

这给了我类似的东西:

908715       40 -rwxrwxr-x    1 david            staff               16542 Nov 15 14:12 ./dump_info.py
908723        0 drwxr-xr-x    2 david            staff                  68 Nov 20 17:35 ./metadata

进入 csv 输出?它看起来像:

908715,40,-rwxrwxr-x,1,david,staff,16542,Nov 15 14:12,./dump_info.py
908723,0,drwxr-xr-x,2,david,staff,68,Nov 20 17:35,./metadata

这是一个文件名中带有空格的示例标题:

652640,80,-rw-rw-r--,1,david,staff,40036,Nov,6,15:32,./v_all_titles/V Catalog Report 11.5.xlsx

【问题讨论】:

    标签: linux unix csv find


    【解决方案1】:

    在命令行中输入有点长,但它正确地保留了文件名中的空格(并加上引号!)

    find . -ls | python -c '
    import sys
    for line in sys.stdin:
        r = line.strip("\n").split(None, 10)
        fn = r.pop()
        print ",".join(r) + ",\"" + fn.replace("\"", "\"\"") + "\""
    '
    

    【讨论】:

    • 当,这很酷(还需要替换文件名末尾的")。
    • 有没有办法在 bash 脚本中执行多行 python?还是必须全部排成一行?
    • 这是一个多行 Python 脚本,适合直接包含在 bash 脚本中(因为它是用 ' 分隔的)。
    • 顺便说一句,如果要在文件名中保留空格,可以在最后一行使用print ",".join(r[:7]) + "," + " ".join(r[7:]) + ",\"" + fn.replace...
    【解决方案2】:

    还有另一个变种。请参阅find 手册页中的“-printf 格式”部分进行自定义。

    $ find . -type f -fprintf /tmp/files.txt "%i,%b,%M,%n,%u,%g,%s,%CY-%Cm-%Cd %CT,%p\n"
    

    示例输出:

    $ less /tmp/files.txt
    
    3414558,40,-rw-rw-r--,1,webwurst,webwurst,16542,2014-09-18 15:54:36.9232917780,./dump_info.py
    3414559,8,-rw-rw-r--,1,webwurst,webwurst,68,2014-09-18 15:54:51.1752922580,./metadata
    

    【讨论】:

      【解决方案3】:

      如果您不关心日期中的空格:

      $ find . -ls | tr -s ' ' ,
      

      如果您确实关心这些空间:

      $ find . -ls | awk '{printf( "%s,%s,%s,%s,%s,%s,%s,%s %s %s,%s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11 )}'
      

      如果您的文件名包含任何空格,这些都不起作用。作为处理文件名中空格的技巧,您可以尝试:

       ... | sed 's/,/ /8g'
      

      去掉除前 8 个逗号之外的所有逗号(假设您的 sed 像 gnu sed 一样支持非标准的 8g 选项)。当然这不会处理文件名中的逗号。

      【讨论】:

      • 文件名中有空格怎么办?
      • tr 解决方案会将文件名中的空格替换为逗号。 awk 解决方案将无法在空格后打印文件名的任何部分。如果文件名包含换行符,则输出将是多行的。此外,如果任何文件名包含逗号,则您的 csv 格式将不正确。如果这些问题是相关的,则需要做更多的工作。也许只是将输出传递给 sed 并删除不需要的逗号将处理文件名中的空格......
      • @WilliamPursell 和 sed 可能也不起作用...他的文件名可能是 foo bar .t xt...啊!!!我的意思是不止一个空格,foo_ _ _ bar.tx _ _t
      【解决方案4】:

      这是我起草的 Python 脚本...

      #!/opt/app/python/bin/python
      # Convert ls output to clean csv    Paolo Villaflores 2015-03-16
      #
      # Sample usage: ls -l | ls2csv.py
      #
      # Features:
      #   accepts -d argument to change dates to yyyy-mm-dd_hhmm format
      #   input is via stdin
      #   separate file/directory field
      #   handle -dils type input (find -ls) versus -l
      #   handle space in filename, by applying quotes around filename
      #   handle date - format into something excel can handle correctly, whether it is from current year or not.
      #   adds a header
      #   handle symlinks - type l
      
      
      
      import sys
      from datetime import datetime
      
      b0=True
      
      def is_f(s):
        if s == '-':
          return 'f'
        return s
      
      for line in sys.stdin:
          if len(line) < 40:
            continue
          if b0:
            b1=line[0] in ['-', 'd', 'c', 'l'] # c is for devices e.g. /devices/pseudo/pts@0:5, l is for symbolic link
            b0=False
            if b1:  # true when shorter ls -l style 8/9 columns. 9 for symlink
              cols=7
              print "d,perms,#links,owner,group,size,modtime,name,symlink"
            else:
              cols=9
              print "inode,bsize,d,perms,#links,owner,group,size,modtime,name,symlink"
          r = line.strip("\n").split(None, cols+1)
          if len(r) < cols+1:
            continue
          if r[cols-7][0] == 'c':
             continue  # ignore c records: devices
          fn = r.pop()
          if b1:
            c = ''
          else:
            c = ",".join(r[0:2]) + ","
          z = 0
          z = r[cols].find(':')
          if z < 0:
            d = r[cols - 1] + "/" + r[cols - 2] + "/" + r[cols]
          else:
            n = str(datetime.now()  )
            d = ''
            # handle the case where the timestamp has no year field
            tm=datetime.strptime(r[cols-2]+ " " + r[cols-1]+ " " + n[:4] +" " + r[cols], "%b %d %Y %H:%M")
            if (tm-datetime.now()).days > 0:
              d = r[cols - 1] + "/" + r[cols - 2] + "/" + str((datetime.now().year-1)) + " " + r[cols]
              tm=datetime.strptime(r[cols-2]+ " " + r[cols-1]+ " " + str(int(n[:4])-1) +" " + r[cols], "%b %d %Y %H:%M")
            else:
              d = r[cols - 1] + "/" + r[cols - 2] + "/" + " ".join([n[:4], r[cols] ] )
            if len(sys.argv) > 1 and sys.argv[1] == '-d':
              d=tm.strftime("%Y-%m-%d_%H%M")
      
          y = fn.find(">")
          symlink=''
          if y > 0:
             symlink = ',\"' + fn[y+2:] + '"'
             fn = fn[:y-2]
          if  fn.find( " ") <0:
            if fn.find('"') <0:
              fn2=fn
            else:
              fn2="'" + fn + "'"
          else:
            fn2="'" + fn + "'"
          print c+ is_f(r[cols-7][0]) + ",\"" + r[cols-7][1:] + "\"," + ",".join(
            r[cols-6:cols-2]) + "," + d + "," + fn2 + symlink
      

      【讨论】:

        【解决方案5】:

        这应该可以完成工作

         find . -ls|awk 'BEGIN{OFS=","}$1=$1'
        

        【讨论】:

        • 请看上面我问的问题——如果文件名中有空格怎么办? (有哪些)
        【解决方案6】:
        ls target 
        
        boto3-1.11.3-py2.py3-none-any.whl
        engagment-states-batch-rds-loader-0.1.27.whl
        mypy_extensions-0.4.3-py2.py3-none-any.whl
        mysql_connector_python-8.0.15-cp36-cp36m-macosx_10_13_x86_64.whl
        pandas-0.25.3-cp36-cp36m-macosx_10_9_x86_64.whl
        retrying-1.3.3-py3-none-any.whl
        structlog-19.2.0-py2.py3-none-any.whl
        typing-3.7.4.1-py3-none-any.whl
        
        
        echo $(ls target) | tr ' ' ,
        
        boto3-1.11.3-py2.py3-none-any.whl,engagment-states-batch-rds-loader-0.1.27.whl,mypy_extensions-0.4.3-py2.py3-none-any.whl,mysql_connector_python-8.0.15-cp36-cp36m-macosx_10_13_x86_64.whl,pandas-0.25.3-cp36-cp36m-macosx_10_9_x86_64.whl,retrying-1.3.3-py3-none-any.whl,structlog-19.2.0-py2.py3-none-any.whl,typing-3.7.4.1-py3-none-any.whl
        

        【讨论】:

          【解决方案7】:

          你可以使用sed -r

          (
          _space_="\ *";
          type=".";
          perm="[^\ ]*";
          hlinks=$perm;
          user=$perm;
          group=$perm;
          size="[0-9]*";
          modified=".{12}";
          name=".*";
          ls -l /etc | sed -r s/"^($type)($perm)$_space_($hlinks)$_space_($user)$_space_($group)$_space_($size)$_space_($modified)$_space_($name)"/'"\1","\2","\3","\4","\5","\6","\7","\8"'/g
          )
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-08-22
            • 1970-01-01
            • 2021-05-25
            • 2021-01-01
            • 1970-01-01
            • 2019-05-01
            • 1970-01-01
            • 2014-11-26
            相关资源
            最近更新 更多