none
pick top 50 files from a file folder RRS feed

  • Question

  • can anyone please advise how to pick top 50 files from a file folder and move to another folder ?


    Reason101

    Monday, March 23, 2020 10:52 PM

Answers

  • hi, can you try pls

      string sourceFile = @"path\"; 
                var directory = new DirectoryInfo(sourceFile);
    
                var files = directory.GetFiles()
                    .Where(x => x.Name.EndsWith(".pdf"))
                     .OrderBy(x => x.LastWriteTime)
                     .Take(50).ToList();
    
    
                foreach (FileInfo file in files)
                {
                    string extention = System.IO.Path.GetExtension(file.Name); 
                    System.IO.File.Copy(sourceFile + file.Name, sourceFile + file.Name.Replace(extention,".txt"));
                }

    • Marked as answer by Reason101 Wednesday, March 25, 2020 7:00 AM
    Tuesday, March 24, 2020 12:26 PM

All replies

  • When indicting top 50, for clarity does that mean of all files in a folder no matter of file type, date created etc? Any other details ?

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Monday, March 23, 2020 10:57 PM
    Moderator
  • yes any files present in the folder, basically only pdf files will be dropped in that folder

    Reason101

    Monday, March 23, 2020 11:08 PM
  • hi, can you try it

       string sourceFile = @"";
                string destinationFile = @"";
    
                var files = System.IO.Directory.GetFiles(sourceFile)
                    .Where(x => x.EndsWith(".pdf"))
                    .Take(50).ToList();
    
    
                foreach (var file in files)
                {
                    var fileName = System.IO.Path.GetFileName(file);
                    //System.IO.File.Move($"{sourceFile}{fileName}", $"{destinationFile}{fileName}");
    
                    System.IO.File.Move(sourceFile + fileName, destinationFile + fileName);
                }

    Monday, March 23, 2020 11:34 PM
  • thanks Murat.

    1) How about if I am asked depending on timestamp, take the latest 50 files. Then how can I modify the code ?

    2) Also, can this Path can be dynamically configurable ? rather than changing in the code ?


    Reason101

    Monday, March 23, 2020 11:42 PM
  • thanks Murat.

    1) How about if I am asked depending on timestamp, take the latest 50 files. Then how can I modify the code ?

    2) Also, can this Path can be dynamically configurable ? rather than changing in the code ?


    Reason101

    Now this is what I was asking, it's all about details, all details and that is why I have not replied with code yet, saw this coming.

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Monday, March 23, 2020 11:45 PM
    Moderator
  • Hi,

    As Karen mentioned, you need to specify the meaning of "top 50".
    e.g. file size, time stamp, file name, etc.

    Regards,

    Ashidacchi -- http://hokusosha.com

    Monday, March 23, 2020 11:52 PM
  • hi,

      string sourceFile = @"sourceFile\";
                string destinationFile = @"destinationFile\";
                var directory = new DirectoryInfo(sourceFile);
    
                var files = directory.GetFiles()
                    .Where(x => x.Name.EndsWith(".pdf"))
                     .OrderBy(x => x.LastWriteTime)
                     .Take(50).ToList();
    
    
                foreach (FileInfo file in files)
                {
                    System.IO.File.Move(sourceFile + file.Name, destinationFile + file.Name);
                }

    you can sen folder location to sourceFile variable from UI

    and you can add parameters Where options

    Tuesday, March 24, 2020 12:03 AM
  • Thanks Murat.

    Actually I just got the requirement. It needs to be updated in the same folder itself. We should not be moving to another folder.

    E.g : Folder A has 200 files, my logic should determine 50 files and then update the extension within the same folder. 


    Reason101

    Tuesday, March 24, 2020 5:57 AM
  • Hi Reason101,

    The folder path is not important.

    If you want to modify the suffix of some files inside this folder, we still need to use File.Move ().

                foreach (FileInfo f in infos)
                {
                    string[] strs = f.Name.Split(new char[]{ '.' });
                    File.Move(f.FullName, Path.Combine(f.DirectoryName, strs[0]+".txt"));
                }

    The idea is the same.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, March 24, 2020 7:26 AM
  • [...]

    E.g : Folder A has 200 files [...]

    By the way, if you expect a much larger number of files, you can also consider some alternative solutions, because GetFiles and OrderBy requires the full list of files to be loaded into memory, which sometimes is inefficient.


    Tuesday, March 24, 2020 12:14 PM
  • hi, can you try pls

      string sourceFile = @"path\"; 
                var directory = new DirectoryInfo(sourceFile);
    
                var files = directory.GetFiles()
                    .Where(x => x.Name.EndsWith(".pdf"))
                     .OrderBy(x => x.LastWriteTime)
                     .Take(50).ToList();
    
    
                foreach (FileInfo file in files)
                {
                    string extention = System.IO.Path.GetExtension(file.Name); 
                    System.IO.File.Copy(sourceFile + file.Name, sourceFile + file.Name.Replace(extention,".txt"));
                }

    • Marked as answer by Reason101 Wednesday, March 25, 2020 7:00 AM
    Tuesday, March 24, 2020 12:26 PM
  • using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    
    namespace csWinForms
    {
        public partial class Form1 : Form
        {
            public class FileDateSorter : System.Collections.IComparer
            {
                int System.Collections.IComparer.Compare(Object x, Object y)
                {
                    // Pre-initialize the return value to return EQUALITY.  Return this if any 
                    // validations fail.
                    int r = 0;
    
                    // X and Y must be strings and those strings must be filepaths to existing files
                    bool xValid = (x.GetType().Equals(typeof(string)) && System.IO.File.Exists((string)x));
                    bool yValid = (y.GetType().Equals(typeof(string)) && System.IO.File.Exists((string)y));
    
                    if (xValid && yValid)
                    {
                        // There are an awful lot of timestamp properties attached to any file.  This function 
                        // uses the last MODIFIED timestamp.  You may prefer to get CREATED or any other.
                        System.DateTime xDate = System.IO.File.GetLastWriteTime((string)x);
                        System.DateTime yDate = System.IO.File.GetLastWriteTime((string)y);
    
                        // Now we have the dates we want to work with, so just compare those and return that
                        r = System.DateTime.Compare(xDate, yDate);
                    }
    
                    return r;
                }
            }
    
            public Form1()
            {
                InitializeComponent();
            }
    
            // Set up a folder browser control to allow user to select directory.
            System.Windows.Forms.FolderBrowserDialog fbd = null;
            string
                // Set up a var to track the last selected directory in the folder browser.
                usingDirectory = string.Empty
            ;
    
            private void ShowFolderBrowser()
            {
                System.Windows.Forms.DialogResult dr = this.fbd.ShowDialog();
                if (dr == DialogResult.OK)
                {
                    // Update the locally selected directory var
                    this.usingDirectory = this.fbd.SelectedPath;
                    // The next time the folder browser is shown, it should 
                    // default to the last selected directory
                    // This will persist until the app is restarted
                }
            }
    
            private string[] GetRecentFiles(string extension, int max)
            {
                string[] r = System.IO.Directory.GetFiles(this.usingDirectory, @"*." + extension);
    
                // Default the max value to whatever you like if a consumer passes 0.  This default 
                // is 50.
                if (max == 0) { max = 50; }
    
                // Sort the array using the IComparer above.
                Array.Sort(r, new FileDateSorter());
                // The array sorter will sort ASCENDING, meaning oldest first, so in order to get 
                // the most recently accessed files you just have to reverse the array
                Array.Reverse(r);
    
                // Now the files are sorted by date/time, just chop off any items that exceed the 
                // specified max
                if (r.Length > max) { Array.Resize<string>(ref r, max); }
                
                return r;
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                this.fbd = new FolderBrowserDialog();
                this.fbd.ShowNewFolderButton = false;
                // Set up a default directory pointing wherever you want.  You won't be able 
                // to browse "above" this point so I'm using MyComputer, allowing full system
                // access including all connected storage devices
                this.fbd.RootFolder = System.Environment.SpecialFolder.MyComputer;
                
                
    
                // You can move the following code lines into a button click or menu item click event
                this.ShowFolderBrowser();
                string[] top50byLastModifiedDate = this.GetRecentFiles(@"pdf", 50);
    
                // To change file extensions
                for (int i = 0; i < top50byLastModifiedDate.Length; i++)
                {
                    string oldname = top50byLastModifiedDate[i];
                    // You can either REPLACE the existing extension
                    //string newname = System.IO.Path.GetDirectoryName(oldname) + @"\" + System.IO.Path.GetFileNameWithoutExtension(oldname) + @".newextension";
                    // Or you can APPEND TO the existing extension
                    string newname = oldname + @".newextension";
    
                    // Update the filesystem entry first
                    System.IO.File.Move(oldname, newname);
                    // Update your array next, in case you want to use this again later
                    top50byLastModifiedDate[i] = newname;
                }
            }
    
            void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                fbd.Dispose();
            }
        }
    }

    Next time and every other time you post on any Forum at all, put the full specification in the OP.  This thread is ridiculous.

    Before you can learn anything new you have to learn that there's stuff you don't know.

    Tuesday, March 24, 2020 4:34 PM
  • A bit off topic, but since I'm in this thread - what would you suggest for lots of files and also what would you suggest for reading huge files and jumping to particular line? I do have some utilities and bash to do these tasks, but I wanted to have a C# code to and was trying to program based on a few stackoverflow threads and nothing recently worked for me.

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    Tuesday, March 24, 2020 5:10 PM
    Moderator
  • A bit off topic, but since I'm in this thread - what would you suggest for lots of files and also what would you suggest for reading huge files and jumping to particular line? I do have some utilities and bash to do these tasks, but I wanted to have a C# code to and was trying to program based on a few stackoverflow threads and nothing recently worked for me.

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    My TechNet articles

    Looking at your 300k points I feel like I shouldn't have to say that you need to start your own thread with this slightly overlapping but not-in-fact-related question.

    There isn't anything you can do with "lots of files" in DotNET.  You'll always get a string array.  You need to use the WinAPI with FindFirstFile/FindNextFile/FindCloseFile to get any legitimate performance boost.

    Jumping to a particular line in a text file is a little easier using a TextReader as opposed to a raw FileStream.  The TextReader typically identifies linebreaks even if they aren't 0x0d0a, so jumping to any given line is as simple as reading and discarding line-by-line until you reach the desired line index. 

    I tend to use the raw FileStream anyway because it's more extensible by being less fleshed out.  In that case you do your own byte-by-byte search for lineterms and retrieving any given line is just a matter of counting linebreaks until you hit the specified count, then reading the following data until you reach another linebreak. 

    You can also index linebreaks into an array of offsets which is considerably faster with a far lighter memory footprint, so then any line you want is indexed into the linebreak-offsets array, you read that element and seek to that position in the filestream, jump past the linebreak characters, and there you are at the line you wanted.


    Before you can learn anything new you have to learn that there's stuff you don't know.


    Tuesday, March 24, 2020 5:53 PM
  • [...] what would you suggest for lots of files and also what would you suggest for reading huge files and jumping to particular line? [...]

    I think that it is possible to use DirectoryInfo.EnumerateFiles("*.pdf"). A list of FileInfo, the List.BinarySearch function and a custom comparer will be used to keep the last 50 files during the scan.

    To jump to a line and read it, try File.ReadLines(“file.txt”).Skip(number).First( ) or maybe consider a specialized file structure.


    Tuesday, March 24, 2020 6:47 PM
  • Hi Murat, instead of for-each loop can you please help me with for loop on this ? Because the above code is behaving weird and after 1st file, when looping 2nd file it throws error : first file not found. Not sure why it is doing this

    Reason101

    Sunday, March 29, 2020 8:15 AM